了解python线程错误
问题描述
阅读http://bugs.python.org/msg160297,我可以看到Stephen White编写的一个简单脚本,它演示了该异常是如何导致python线程出错的
Exception AttributeError: AttributeError("'_DummyThread' object has no attribute '_Thread__block'",) in <module 'threading'
给定史蒂芬·怀特的源代码(http://bugs.python.org/file25511/bad-thread.py),
import os
import thread
import threading
import time
def t():
threading.currentThread() # Populate threading._active with a DummyThread
time.sleep(3)
thread.start_new_thread(t, ())
time.sleep(1)
pid = os.fork()
if pid == 0:
os._exit(0)
os.waitpid(pid, 0)
如何重写以解决此错误?
解决方案
The bug是因为threading
接口在外线程上调用threading.currentThread()
时创建的虚拟线程对象与threading._after_fork
函数(在调用os.fork()
后被调用以清理资源)之间的交互不好。
要在不修改Python源代码的情况下解决该错误,请使用__stop
的无操作实现:
import threading
threading._DummyThread._Thread__stop = lambda x: 42
错误的原因最好在Richard Oudkerk和cooyeah的评论中缩小范围。发生的情况如下:
threading
模块允许从非由threading
API调用创建的线程调用threading.currentThread()
。然后,它返回一个"哑线程"实例,该实例支持Thread
API的一个非常有限的子集,但对于标识当前线程仍然有用。threading._DummyThread
作为Thread
的子类实现。Thread
实例通常包含一个内部可调用的(self.__block
),该内部可调用保持对为该实例分配的操作系统级锁的引用。由于可能最终使用self.__block
的公共Thread
方法都被_DummyThread
覆盖,_DummyThread
的构造函数有意通过删除self.__block
来释放操作系统级锁。
/li>threading._after_fork
打破封装并在所有注册线程上调用私有Thread.__stop
方法,包括虚拟线程,其中__stop
从未打算被调用。(它们不是由Python启动的,因此它们的停止也不是由Python管理的。)由于伪线程不知道__stop
,它们从Thread
继承,该实现愉快地访问_DummyThread
实例中不存在的私有__block
属性。此访问最终导致错误。
删除__block
时,通过modifying Thread.__stop
not to break修复了2.7分支中的错误。3.x分支将__stop
拼写为_stop
,因此受保护,并将其修复为overriding _DummyThread
's _stop
to do nothing。
相关文章