在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()
当我启动服务器然后启动客户端时,每次客户端完成僵尸进程时都会保留。
如何更改代码,以便不再保留僵尸进程?
答案 0 :(得分:3)
通常的技巧是跟踪所有的儿童按钮,以便在主要进程退出时或者您希望清理儿童时将其杀死。
您可以根据需要定期轮询和收听流程,或等到您即将退出。
有关如何执行此操作的示例,请查看collect_children()中ForkingMixin的SocketServer module代码。
os module有许多工具可用于管理os.wait()和os.kill等子流程。
我不知道它是否适合您的问题,但multiprocessing.Pool()可能会有所帮助。它自动管理子进程池并将其重用于将来的任务。当进程之间只有有限的数据交换以及工作是否相对同质(所有子进程都在做同样的工作)时,它主要是有用的。
答案 1 :(得分:0)
当进程退出时,它会保留在进程表中,直到某些内容读取其返回代码。假设这是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()