[英]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.