[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