父进程发送的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
相关产品推荐
相关产品推荐

