2013-04-08 134 views
11

我有一個Python 2.7多進程進程不會退出父進程退出。我設置了守護進程標誌,強制它在父母死亡時退出。該文檔聲明:多進程守護進程不會終止在父進程退出

「當進程退出時,它會嘗試終止其所有守護進程的子進程。」

p = Process(target=_serverLaunchHelper, args=args) 
p.daemon = True 
print p.daemon # prints True 
p.start() 

當我經由守護程序活下來和運行kill命令終止該父進程(該塊上的下一次運行的端口)。子進程正在啓動一個SimpleHttpServer,並在不做任何事情的情況下調用serve_forever。我的猜測是,文檔中的「企圖」部分意味着阻塞服務器進程正在停止進程死亡,並導致進程因此而孤立。我可以讓孩子將服務推送到另一個線程,並讓主線程檢查父進程ID更改,但是這似乎只是複製守護進程功能的很多代碼。

有人能夠洞察守護程序標誌不按描述工作的原因嗎?這在Windows8 64位和ubuntu12 32位虛擬機上是可重複的。

一個歸結處理功能的版本低於:

def _serverLaunchHelper(port) 
    httpd = SocketServer.TCPServer(("", port), Handler) 
    httpd.serve_forever() 

回答

9

當一個進程退出時,它會試圖終止其所有惡魔的子進程。

這裏的關鍵詞是「企圖」。此外,「退出」。

根據您的平臺和實施情況,這可能是終止守護程序子進程的唯一方法是明確地執行此操作。如果父進程正常退出,它有機會明確這樣做,所以一切都很好。但是,如果父進程突然終止,它不會。

對於CPython的特別,如果你看一下the source,終止惡魔的過程中的處理方式爲加入非惡魔的過程相同:通過在atexit功能走active_children()。所以,當且僅當你的atexit處理程序開始運行時,你的守護進程纔會被殺死。而且,作爲該模塊的文件說:

注:當程序被不Python,檢測一個Python致命的內部錯誤時,或當os._exit()處理的信號打死不叫通過該模塊註冊的功能叫做。

根據你如何殺死父母,你可以通過添加一個信號處理程序來攔截突然終止來解決這個問題。但是你可能不會 - 例如,在POSIX上,SIGKILL不能被攔截,所以如果你kill -9 $PARENTPID,這不是一個選項。

另一個選擇是殺死進程組,而不是僅僅是父進程。例如,如果您的父母擁有PID 12345,則Linux上的kill -- -12345將會終止它及其所有子項(假設您沒有做任何事情)。

+3

好的,所以如果我真的想確保孩子在父母死後退出,我需要將邏輯編程到子進程中,以監視父母的消失。感謝您的明確和快速的答案! – Pyrce 2013-04-08 20:32:57