[Python-bugs-list] [ python-Bugs-233665 ] Race condition in threading (Conditions)

nobody nobody@sourceforge.net
Mon, 26 Feb 2001 11:17:18 -0800


Artifact #233665, was updated on 2001-02-22 13:15
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=233665&group_id=5470

Category: Threads
Group: Not a Bug
Status: Closed
Priority: 4
Submitted By: Nobody/Anonymous
Assigned to: Tim Peters
Summary: Race condition in threading (Conditions)

Initial Comment:
Here is a race condition involving a _Condition() object cond and a predicate called condition.

Thread A executes:
	cond.acquire()
	while not condition:
		cond.wait() <--

A goes into wait():
	waiter = _allocate_lock()
	waiter.acquire()
	self.__waiters.append(waiter)
	saved_state = self._release_save() <--

A finishes that last line and is interrupted by Thread B. A has released cond's lock, so B continues (who was previously blocked at cond.acquire()):
	cond.acquire()
	condition = 1
	cond.notifyAll()
	cond.release()

Back to A:
	if timeout is None:
		waiter.acquire() <--

A blocks here and completely misses the notifyAll() call. Even though it called wait() before notifyAll(), it will now wait indefinatly for the next notify()/notifyAll() call (which may be never).
I have run into this thread race bug in my program several times. A POSIX-like atomic operation that releases a mutex and then grabs another would be very useful here. Any suggestions?


----------------------------------------------------------------------

Comment By: Tim Peters
Date: 2001-02-26 11:17

Message:
Logged In: YES 
user_id=31435

Closing as NotABug in the absence of more info, as 
explained in the followup 3 days ago.

----------------------------------------------------------------------

Comment By: Tim Peters
Date: 2001-02-23 00:11

Message:
You're going to have to work a lot harder to convince me that A can block.  When cond.notifyAll() is executed, *all* the waiters in self.__waiters get released.  It's certain that the waiter W allocated by A is in self.__waiters at that point, because the append of W was protected by the condvar lock, and B can't do cond.notifyAll() before it does cond.acquire().

Therefore W is in self.__waiters when cond.notifyAll() is executed; therefore cond.notifyAll()'s

for waiter in waiters: waiter.release()

executes W.release() in particular; therefore A's W.acquire() succeeds sooner or later after that.

IOW, A cannot block on waiter.acquire(), because notifyAll() does waiter.release().

I agree this *would* be a bug if A could block here, but, as above, I see no reason to believe that it can.

Have reduced priority, and will close as NotABug tomorrow in the absence of more info.

----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=233665&group_id=5470