Understand Python Threading Bug
Solution 1:
The bug occurs because of a bad interaction between dummy thread objects created by the threading
API when one calls threading.currentThread()
on a foreign thread, and the threading._after_fork
function, called to clean up resources after a call to os.fork()
.
To work around the bug without modifying Python's source, monkey-patch threading._DummyThread
with a no-op implementation of __stop
:
import threading
threading._DummyThread._Thread__stop = lambda x: 42
The cause of the bug is best narrowed down in comments by Richard Oudkerk and cooyeah. What happens is the following:
The
threading
module allowsthreading.currentThread()
to be called from a thread not created by thethreading
API calls. It then returns a "dummy thread" instance which supports a very limited subset of theThread
API, but is still useful for identifying the current thread.threading._DummyThread
is implemented as a subclass ofThread
.Thread
instances normally contain an internal callable (self.__block
) that keeps reference to an OS-level lock allocated for the instance. Since publicThread
methods that might end up usingself.__block
are all overridden by_DummyThread
,_DummyThread
's constructor intentionally releases the OS-level lock by deletingself.__block
.threading._after_fork
breaks the encapsulation and calls the privateThread.__stop
method on all registered threads, including the dummy ones, where__stop
was never meant to be invoked. (They weren't started by Python, so their stopping is not managed by Python either.) As the dummy threads don't know about__stop
, they inherit it fromThread
, and that implementation happily accesses the private__block
attribute that doesn't exist in_DummyThread
instances. This access finally causes the error.
The bug is fixed in the 2.7 branch by modifying Thread.__stop
not to break when __block
is deleted. The 3.x branch, where __stop
is spelled as _stop
and therefore protected, fixes it by overriding _DummyThread
's _stop
to do nothing.
Post a Comment for "Understand Python Threading Bug"