如何使用信号处理程序停止并恢复子进程?代码无法恢复子进程是什么原因
问题原因
你的代码存在几个关键逻辑错误,直接导致进程组被停止无法继续运行:
- 变量笔误(如果你的代码能运行说明实际代码已修正该问题):
fork()的返回值赋值给了global_pid,但后续判断用的是未声明的pid变量,编译阶段就会报错。
- 变量笔误(如果你的代码能运行说明实际代码已修正该问题):
- 信号处理上下文错误:
int3指令是子进程执行的,触发的SIGTRAP(信号值5)是发送给子进程的,子进程继承了父进程的信号处理函数,实际是子进程在执行stop函数,而子进程中global_pid的值为0(fork给子进程的返回值是0)。
- 信号处理上下文错误:
- 停止范围错误:
kill(0, SIGSTOP)的含义是给当前进程所在的整个进程组发送停止信号,会直接把父进程和子进程都暂停,stop函数中后续发SIGCONT的代码根本没有运行机会,这就是你看到终端输出Stopped的原因。
- 停止范围错误:
- (非核心不影响运行但不规范)信号处理函数中调用
printf属于不安全操作,printf是不可重入函数,信号处理可能打断正常的标准IO操作,导致输出异常。
- (非核心不影响运行但不规范)信号处理函数中调用
修复方案
如果你的需求是子进程触发断点时,由父进程控制子进程的停止和恢复,调整逻辑如下:
- 子进程收到
SIGTRAP后通知父进程,由父进程完成对信号的处理,不要在子进程的信号处理函数中操作停止逻辑 - 父进程需要等待子进程的状态变化,不要直接sleep后退出
- 避免在信号处理函数中使用不可重入函数
修正后示例代码
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/wait.h> #include <unistd.h> #include <sys/types.h> #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ }while(0) pid_t child_pid = -1; void parent_handler(int signo) { // 信号处理函数用可重入的write输出 const char msg[] = "catch SIGTRAP from child, stop then resume child\n"; write(STDOUT_FILENO, msg, sizeof(msg)-1); // 父进程操作子进程 kill(child_pid, SIGSTOP); // 此处可添加你需要的暂停处理逻辑 sleep(1); kill(child_pid, SIGCONT); } void child_handler(int signo) { // 子进程收到SIGTRAP后转发通知父进程 kill(getppid(), SIGUSR1); } int main() { printf("before fork, pid = %d\n",getpid()); pid_t pid = fork(); child_pid = pid; if(pid == -1) { ERR_EXIT("fork error"); } if(pid > 0) { // 父进程注册SIGUSR1处理函数,接收子进程的断点通知 signal(SIGUSR1, parent_handler); printf("This is parent pid = %d child pid = %d\n",getpid(),pid); // 等待子进程退出 wait(NULL); printf("child exit, parent exit\n"); }else if(pid == 0) { // 子进程注册SIGTRAP处理函数 signal(SIGTRAP, child_handler); printf("This is child pid = %d parent pid = %d\n",getpid(),getppid()); asm volatile("int3"); printf("The child continued.\n"); exit(0); } return 0; }
内容的提问来源于stack exchange,提问作者gazile
相关产品推荐
相关产品推荐

