Python外部杀死主进程未连带终止子守护进程问题咨询
修复方案
根因说明
你直接kill主进程时,主进程默认会直接终止,不会执行ev_killing_switch.wait()之后的清理逻辑。你设置的daemon属性仅在主进程正常退出时生效,直接终止的场景下daemon子进程会被系统init进程接管,变为孤儿进程残留。
方案1:Python主进程添加信号处理逻辑(推荐)
无需修改shell侧逻辑,仅修改launcher.py代码,捕获外部终止信号后走你预设的正常退出流程即可:
import sys import multiprocessing as mp import signal def main(): set_start_method("spawn") ev_killing_switch = mp.Event() # 新增信号处理函数 def termination_handler(signum, frame): if not ev_killing_switch.is_set(): ev_killing_switch.set() # 绑定终止信号处理逻辑,覆盖默认直接退出的行为 signal.signal(signal.SIGTERM, termination_handler) # 响应kill默认发送的信号 signal.signal(signal.SIGINT, termination_handler) # 响应Ctrl+C触发的中断信号 # 原有子进程启动逻辑保持不变 child_01 = mp.Process(target=Child_01_Initializer, args=(...), daemon=True) child_01.start() child_02 = mp.Process(target=Child_02_Initializer, args=(ev_killing_switch, ...), daemon=True) child_02.start() child_03 = mp.Process(target=Child_03_Initializer, args=(...), daemon=True) child_03.start() child_04 = mp.Process(target=Child_04_Initializer, args=(...), daemon=True) child_04.start() ev_killing_switch.wait() print("System stopped, terminating all processes.") sys.exit(0)
修改后不管是子进程触发退出事件,还是外部执行kill <主进程PID>、pkill -f launcher.py操作,都会触发正常清理流程,所有daemon子进程会自动同步关闭。
方案2:Shell侧杀整个进程组(无需修改Python代码)
Linux下同一父进程启动的子进程默认和父进程属于同一个进程组,进程组ID和主进程PID一致,直接杀整个进程组即可一次性清理所有相关进程,无需逐个收集子进程PID:
- 首先查询
launcher.py的主进程PID,假设为12345 - 执行命令杀整个进程组:
kill -- -12345
也可以直接用pkill按进程名匹配杀整个组:pkill -f -g 0 launcher.py
注意:该方案会直接给所有进程发送终止信号,不会触发主进程预设的清理逻辑,如果你的业务有退出前需要执行的收尾操作,优先选择方案1。
内容的提问来源于stack exchange,提问作者Carlo
相关产品推荐
相关产品推荐

