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

父进程发送的SIGTERM信号无法触发子进程的信号处理程序?

问题分析与解决方案

这是个典型的信号处理排查问题,我帮你梳理几个最可能的原因,以及对应的验证和解决方法:

1. 信号处理函数的注册方式不匹配

你的信号处理函数是带siginfo_t*参数的三参数版本,这种情况下必须使用sigaction()函数注册,并且要设置SA_SIGINFO标志——如果用了传统的signal()函数注册,系统可能无法正确识别这个带扩展参数的处理器,导致SIGTERM信号触发时没有执行你的自定义逻辑(而SIGCONT可能刚好因为某些系统兼容特性触发了,但这不是规范用法)。

正确的注册代码应该是这样的:

#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void custom_signal_handler(int signum, siginfo_t* info, void* ptr) {
    if (signum == SIGTERM) {
        printf("1\n");
    } else if (signum == SIGCONT) {
        printf("2\n");
    }
}

int main() {
    // ... 其他代码,比如fork子进程 ...

    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction = custom_signal_handler;
    sa.sa_flags = SA_SIGINFO; // 关键:必须设置这个标志才能使用三参数处理器

    // 分别注册SIGTERM和SIGCONT
    if (sigaction(SIGTERM, &sa, NULL) == -1) {
        perror("Failed to register SIGTERM handler");
        exit(EXIT_FAILURE);
    }
    if (sigaction(SIGCONT, &sa, NULL) == -1) {
        perror("Failed to register SIGCONT handler");
        exit(EXIT_FAILURE);
    }

    // ... 后续逻辑 ...
}

2. 子进程的SIGTERM信号被阻塞

有可能子进程在某个操作中调用了sigprocmask()阻塞了SIGTERM信号,导致信号无法被递送。你可以在子进程中添加代码排查:

sigset_t mask;
sigprocmask(SIG_BLOCK, NULL, &mask);
if (sigismember(&mask, SIGTERM)) {
    printf("SIGTERM is blocked in child process\n");
}

如果发现SIGTERM被阻塞,需要检查代码中是否有不必要的信号阻塞逻辑,或者在合适的时机用sigprocmask(SIG_UNBLOCK, &term_mask, NULL)解除阻塞。

3. 父进程发送信号的目标PID错误

虽然SIGCONT能正常触发,但还是要确认父进程保存的childPid是否正确:

  • 确保父进程在fork()后,正确保存了返回的子进程PID(fork()返回0是子进程,父进程得到的返回值才是子进程PID);
  • 在父进程发送信号前,打印childPid,同时用ps命令查看系统中实际运行的子进程PID,确认两者一致。

4. 子进程处于无法响应信号的状态

如果子进程正在执行某些不可中断的系统调用(比如某些特殊的IO操作),SIGTERM信号可能会被暂时挂起,直到系统调用完成。不过这种情况比较少见,你可以尝试在子进程中加入一些简单的循环逻辑(比如while(1) { sleep(1); }),再测试父进程发送SIGTERM是否能触发处理函数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:40:26