/bin/sh脚本中trap命令经C++ execvp启动后无法触发的问题
问题解决:execvp启动shell脚本后trap无法触发信号处理
问题原因
- 信号掩码继承:fork创建的子进程会继承调用线程的信号掩码。如果C++程序的线程(调用
fork_process的线程)屏蔽了SIGTERM信号,启动的shell脚本进程会继承这个屏蔽规则,导致trap无法捕获SIGTERM。 - C++代码存在语法错误:
pid变量未声明、char *args[]={"./test.sh",NULL}末尾缺少分号,这些错误会导致编译失败或程序行为异常。
解决方案
1. 在子进程exec前重置信号掩码
在调用execvp之前,清空子进程的信号掩码,确保所有信号(包括SIGTERM)处于未屏蔽状态。
2. 修正C++代码语法错误
补全变量声明和语句结束符,保证代码正常编译运行。
修改后的C++代码示例
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string> #include <signal.h> pid_t fork_process(pid_t &new_pid, const std::string& process_start) { int ws; int status; pid_t pid; // 补全pid变量声明 printf("Parent: %d\n", getpid()); char *args[]={"./test.sh", NULL}; // 添加分号 pid = fork(); if (pid == 0) { printf("Child %d\n", getpid()); // 重置信号掩码,确保所有信号未被屏蔽 sigset_t sigset; sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); int r = execvp(args[0], args); if (r < 0) { const int err = errno; printf("exec failed with errno: %d", err); exit(err); } } new_pid = pid; ws = waitpid(pid, &status, WNOHANG); printf("%d\n", ws); return ws; }
额外说明
- 如果C++程序中存在线程使用
pthread_sigmask屏蔽信号的情况,需确保调用fork_process的线程没有屏蔽SIGTERM,或者在子进程中显式解除屏蔽。 - 单独运行脚本正常是因为直接启动时,shell进程继承的是父shell的信号掩码,而默认情况下父shell不会屏蔽
SIGTERM。
内容的提问来源于stack exchange,提问作者Dasthananda Dassu
相关产品推荐
相关产品推荐

