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

多进程信号处理疑问:子进程终止时父进程为何未触发信号处理?

问题:fork上下文下子进程超时未触发父进程信号处理函数?

我原本理解在fork上下文下,传递给子进程的信号会触发父进程的信号处理函数,但以下示例并未出现预期行为:

import time
import asyncio

from pebble import ProcessPool
import multiprocessing

SLEEP = 10
TIMEOUT = 2
import signal

def function(seconds):
    print(f"Going to sleep {seconds}s..")
    
    
    time.sleep(seconds)
    print(f"Slept {seconds}s.")


def stop(reaons:str="caught signals"):
    print("stopping")

async def main():
    loop = asyncio.get_running_loop()
    pool = ProcessPool(2, context=multiprocessing.get_context("fork"))
    loop.add_signal_handler(signal.SIGINT, stop)
    loop.add_signal_handler(signal.SIGTERM, stop)
 
    try:
        fut = pool.schedule(function, (SLEEP,), timeout=TIMEOUT)

        await asyncio.wrap_future(fut, loop=loop)
    except asyncio.exceptions.TimeoutError:
        print("caught exception")



if __name__ == '__main__':
    asyncio.run(main())

运行输出:

Going to sleep 10s..
caught exception

我原本预期这会触发父进程的stop信号处理函数,请问这是为什么?


回答

核心原因有两点:

  • 你误解了fork上下文的信号传递逻辑
    fork创建的子进程会继承父进程的信号处理函数,但子进程收到信号时,是在子进程自身的进程空间执行该处理函数,而非触发父进程的信号处理函数。不存在“子进程收到信号会触发父进程handler”的机制。

  • pebble的超时机制不依赖向父进程发信号
    你的代码里的TimeoutError是pebble库内部的异步超时通知:当任务超时,pebble会主动终止子进程(可能向子进程发送终止信号),但这个过程中不会向父进程发送SIGINT或SIGTERM信号。父进程捕获的TimeoutError只是库封装的异常,和信号处理完全无关,自然不会触发你注册的stop函数。

如果想在任务超时后执行stop逻辑,不需要依赖信号,直接在except TimeoutError代码块里调用stop()即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:03:20