[英]How to avoid zombie processes in python?
在Python3中,我基本上有以下代码:
server.py:
import os
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 10000))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.listen(5)
while True:
print("waiting")
connection, client_address = sock.accept()
print("received")
child_pid = os.fork()
if child_pid == 0:
print("connection received")
received = connection.recv(1024)
connection.sendall("OK".encode('utf-8'))
os._exit(0)
client.py:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("127.0.0.1", 10000))
sock.close()
当我启动服务器然后启动客户端时,每次客户端完成僵尸进程时都会保留。
如何更改代码,以便没有僵尸进程?
通常的技术是跟踪所有儿童的屁股,以便在主要进程退出时或者您希望清理儿童时将其杀死。
您可以根据需要定期轮询和收集流程,或等到您即将退出。
有关如何执行此操作的示例,请查看ForkingMixin中用于SocketServer模块的collect_children()代码。
os模块有许多用于管理子进程的工具,如os.wait()和os.kill 。
我不知道它是否适合你的问题,但是multiprocessing.Pool()可能会有所帮助。 它自动管理子进程池并将其重用于将来的任务。 当进程之间只有有限的数据交换以及工作是否相对同质(所有子进程都在进行相同类型的工作)时,它主要是有用的。
当进程退出时,它将保留在进程表中,直到某些内容读取其返回代码。 假设这是linux,你可以让它成为守护进程并让init进程处理它。 但你也可以自己调用os.waitpid
。 以下是在后台等待pids的类的示例。 它很好,因为它可以让你的程序退出,直到完全整理它为止。 您可以将其扩展为执行诸如向子进程发送终止信号,记录结果等操作。
import threading
import queue
import os
import time
class ZombieKiller(threading.Thread):
"""Okay, really its just a zombie waiter, but where's the fun in that?
"""
def __init__(self):
super().__init__()
self.pid_q = queue.Queue()
self.start()
def run(self):
while True:
pid = self.pid_q.get()
if pid is None:
return
print(pid, 'wait')
os.waitpid(pid, 0)
print(pid, 'wait done')
def cull_zombie(self, pid):
self.pid_q.put(pid)
def close(self):
self.pid_q.put(None)
self.join()
def test():
zombie_killer = ZombieKiller()
for i in range(3):
pid = os.fork()
if pid == 0:
# child
time.sleep(5)
print(os.getpid(), 'work done')
exit()
else:
# parent
zombie_killer.cull_zombie(pid)
zombie_killer.close()
print('test complete')
test()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.