You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SIGTERM信号传播给subprocess创建的子进程

现象原因
  • Linux系统默认信号仅发送给指定的单个进程,不会自动向下传递给其子进程。执行kill -15 <a.py PID>时,只有a.py进程收到SIGTERM信号。
  • 原始a.py未注册SIGTERM信号处理逻辑,收到信号后直接终止退出,其启动的b.py子进程未收到终止信号,成为孤儿进程被系统init进程托管,因此会持续在后台运行输出日志。
解决方案

要实现多级进程链(a.py->b.py->c.py->d.py)仅最内层配置清理逻辑即可全链路透传信号的要求,可采用进程组信号批量转发方案,实现逻辑如下:

  1. 所有非最内层的父进程(a.py、b.py、c.py)统一添加通用信号转发逻辑,无需处理业务清理:
    • 注册SIGINT、SIGTERM等终止信号的处理函数
    • 启动子进程时通过preexec_fn=os.setsid参数让子进程创建独立进程组,其所有后代进程默认都会归属到该进程组
    • 父进程收到终止信号时,调用os.killpg()将信号转发给子进程对应的整个进程组,所有后代进程都会收到相同的终止信号
  2. 仅最内层进程(如示例中的b.py,多级场景下的d.py)保留业务相关的信号清理逻辑即可,无需额外修改。

修改后的a.py示例代码:

#!/usr/bin/env python3
# a.py
import signal
import subprocess
import os
import sys

child_proc = None

def forward_signal(signum, frame):
    if child_proc:
        # 向子进程所在的整个进程组转发信号,覆盖所有后代进程
        os.killpg(os.getpgid(child_proc.pid), signum)
    sys.exit(128 + signum)

def main():
    global child_proc
    print(f'Starting process {os.getpid()}')
    # 注册需要转发的终止信号
    signal.signal(signal.SIGINT, forward_signal)
    signal.signal(signal.SIGTERM, forward_signal)
    # 启动子进程时让其创建新的进程组
    child_proc = subprocess.Popen('./b.py', preexec_fn=os.setsid)
    child_proc.wait()
    sys.exit(child_proc.returncode)

if __name__ == '__main__':
    main()

如果b.py需要继续启动c.py,仅需给b.py添加上述相同的通用转发逻辑即可,原有清理逻辑无需调整。

内容的提问来源于stack exchange,提问作者user1011113

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 20:36:01