2012-11-02 78 views
13

閱讀http://bugs.python.org/msg160297,我可以看到由斯蒂芬·懷特寫了一個簡單的腳本演示瞭如何蟒蛇線程錯誤了這個異常瞭解蟒蛇線程錯誤

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) 

如何將我們把它重新寫那麼這個錯誤得到解決?

+0

在我看來,你可以將它全部重寫爲'time.sleep(3)'。我想你應該指定重寫的程序應該實際執行的操作。 –

+3

@JanneKarila該程序僅僅演示了一個Python bug,如果你在Python 2.7中運行它,你會看到它。這個請求是爲了解決這個bug而不是升級到修復它的Python版本。 – user4815162342

回答

33

The bug因爲由threading API創建時一個在外國線程調用threading.currentThread()虛擬線程對象之間的互動不良,以及threading._after_fork函數,調用os.fork()呼叫後清理資源的發生。

要解決的bug,而無需修改Python的來源,猴子補丁threading._DummyThread與無操作執行__stop

import threading 
threading._DummyThread._Thread__stop = lambda x: 42 

錯誤的原因是在評論由Richard Oudkerkcooyeah最佳收窄。什麼情況如下:

  1. threading模塊允許threading.currentThread()從沒有被threading API調用創建一個線程調用。然後它返回一個「虛擬線程」實例,它支持Thread API的一個非常有限的子集,但對於識別當前線程仍然有用。

  2. threading._DummyThread實現爲Thread的子類。 Thread實例通常包含一個內部可調用的函數(self.__block),該函數保持對爲該實例分配的操作系統級鎖定的引用。由於公共Thread可能最終使用self.__block的方法全部被_DummyThread覆蓋,因此_DummyThread的構造函數通過刪除self.__block有意釋放OS級鎖。

  3. threading._after_fork打破封裝,並在所有已註冊線程(包括虛擬線程)上調用私有方法Thread.__stop,其中__stop永遠不會被調用。 (它們不是由Python啓動的,所以它們的停止也不是由Python管理)。由於虛擬線程不知道__stop,它們從Thread繼承它,並且該實現愉快地訪問專用的__block屬性,該屬性不存在於_DummyThread實例中。這個訪問最終導致錯誤。

該錯誤是由modifying Thread.__stop not to break__block被刪除固定在2.7分支。 3.x分支,其中__stop拼寫爲_stop因此受保護,將其修復爲overriding _DummyThread's _stop to do nothing

+0

啊...我現在明白了...謝謝! –

+0

精湛的解釋! –