通过信号回收子进程,防止出现僵尸进程
子进程退出时向父进程发送SIGCHILD信号
父进程处理SIGCHILD信号
在信号处理函数中调用 os.waitpid(-1, os.WNOHANG)
# sig.py
from multiprocessing import Process
import logging
import os
import signal
import time
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)-15s - %(levelname)s - %(message)s'
)
def run():
exitcode = 3
logging.info("this is run")
time.sleep(10)
logging.info("run exit")
os._exit(exitcode)
def run233():
logging.info("this is run233")
time.sleep(20)
logging.info("run2333 exit")
def wait_child(*args):
print("+++++++++++ wait_child")
# 一会实验的时候,要改动这里
cpid, status = os.waitpid(-1, os.WNOHANG)
print(pid, status)
#while True:
# cpid, status = os.waitpid(-1, os.WNOHANG)
# print(cpid, status)
# exitcode = status >> 8
# print(exitcode)
# #break
# break
# 添加一个处理信号的程序,每当有子进程退出,都会执行wait_child
signal.signal(signal.SIGCHLD, wait_child)
p = Process(target=run)
p.start()
p1 = Process(target=run233)
p1.start()
print("p",p.pid," p1",p1.pid)
#p.join()
#p1.join()
#print("join end")
while True:
time.sleep(25)
break
# 开启2个会话
# 一个监听python进程
watch -n 1 -c 'ps -ef | grep python'
# 另一个我们的python代码
python sig.py
# 观察监听python进程的变化
cpid, status = os.waitpid(-1, os.WNOHANG)
第一次实验 有这句话
第二次实验注释掉这句话
第三次实验注释掉这句话,然后在p和p1 start()后加上p.join() p1.join()
第四次实验,加上json(),在加上这句话。
重点观察
1.进程的是否退出(python sig.py进程个数)
2.是否出现僵尸进程 [python]
3.加入p.json()前后 观察wait_child 函数中打印的信息
[python] 这个进程是kill 不掉的
可以尝试增加主进程sleep时间,然后再开一个终端去kill -9 这个僵尸进程。
使用 json直接回收
p.join(timeout=5.5) # 阻塞等待回收子进程,5.5秒没结束会产生僵尸进程
if p.is_alive: # 判断是否存活
p.terminate() # 强制结束正在执行的子进程
p.join() # 回收子进程