[英]Zombie state multiprocessing library python3
我的問題涉及在使用 python3 的多處理庫時替換 join() 函數以避免已終止進程的失效或僵屍狀態。 是否有替代方法可以暫停子進程被終止,直到它們從主進程獲得綠燈? 這允許他們在不進入僵屍狀態的情況下正確終止?
我使用以下代碼准備了一個快速說明,它啟動了 20 個不同的進程,第一個進程需要 10 秒的加載工作,所有其他進程需要 3 秒的加載工作:
import os
import sys
import time
import multiprocessing as mp
from multiprocessing import Process
def exe(i):
print(i)
if i == 1:
time.sleep(10)
else:
time.sleep(3)
procs = []
for i in range(1,20):
proc = Process(target=exe, args=(i,))
proc.start()
procs.append(proc)
for proc in procs:
print(proc) # <-- I'm blocked to join others till the first process finishes its work load
proc.join()
print("finished")
如果您啟動腳本,您將看到所有其他進程都進入僵屍狀態,直到第一個進程釋放 join() 函數。 這可能會使系統不穩定或過載!
謝謝
根據此線程,Marko Rauhamaa 寫道:
如果您不想知道子進程何時退出,您可以簡單地忽略 SIGCHLD 信號:
import signal signal.signal(signal.SIGCHLD, signal.SIG_IGN)
這將防止僵屍出現。
wait(2)
手冊頁解釋了:
POSIX.1-2001 規定,如果 SIGCHLD 的處置設置為 SIG_IGN 或為 SIGCHLD 設置了 SA_NOCLDWAIT 標志(請參閱 sigaction(2)),則終止的子進程不會變成僵屍,並且調用 wait() 或 waitpid( ) 將阻塞,直到所有子進程都終止,然后失敗,將 errno 設置為 ECHILD。 (原始 POSIX 標准未指定將 SIGCHLD 設置為 SIG_IGN 的行為。請注意,即使 SIGCHLD 的默認處置是“忽略”,明確地將處置設置為 SIG_IGN 會導致對僵屍進程子進程的不同處理。)
Linux 2.6 符合 POSIX 要求。 但是,Linux 2.4(及更早版本)不會:如果在忽略 SIGCHLD 時進行了 wait() 或 waitpid() 調用,則該調用的行為就像未忽略 SIGCHLD 一樣,也就是說,調用會阻塞直到下一個child 終止,然后返回該 child 的進程 ID 和狀態。
因此,如果您使用的是 Linux 2.6 或兼容 POSIX 的操作系統,則使用上述代碼將允許子進程退出而不會成為僵屍進程。 如果您使用的不是 POSIX 兼容的操作系統,那么上面的線程提供了許多選項。 下面是一種替代方案,有點類似於 Marko Rauhamaa 的第三個建議。
如果由於某種原因您需要知道子進程何時退出並希望以不同方式處理(至少其中一些),那么您可以設置一個隊列以允許子進程在完成時向主進程發出信號。 然后主進程可以按照它從隊列接收項目的順序調用適當的連接:
import time
import multiprocessing as mp
def exe(i, q):
try:
print(i)
if i == 1:
time.sleep(10)
elif i == 10:
raise Exception('I quit')
else:
time.sleep(3)
finally:
q.put(mp.current_process().name)
if __name__ == '__main__':
procs = dict()
q = mp.Queue()
for i in range(1,20):
proc = mp.Process(target=exe, args=(i, q))
proc.start()
procs[proc.name] = proc
while procs:
name = q.get()
proc = procs[name]
print(proc)
proc.join()
del procs[name]
print("finished")
產生類似的結果
...
<Process(Process-10, stopped[1])> # <-- process with exception still gets joined
19
<Process(Process-2, started)>
<Process(Process-4, stopped)>
<Process(Process-6, started)>
<Process(Process-5, stopped)>
<Process(Process-3, stopped)>
<Process(Process-9, started)>
<Process(Process-7, stopped)>
<Process(Process-8, started)>
<Process(Process-13, started)>
<Process(Process-12, stopped)>
<Process(Process-11, stopped)>
<Process(Process-16, started)>
<Process(Process-15, stopped)>
<Process(Process-17, stopped)>
<Process(Process-14, stopped)>
<Process(Process-18, started)>
<Process(Process-19, stopped)>
<Process(Process-1, started)> # <-- Process-1 ends last
finished
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.