Linux C信号处理程序捕获信号后退出、无法触发SIGSEGV等问题求助
问题解答
问题1:信号捕获后程序直接终止的解决方法
导致该问题的原因有三个,对应解决方式如下:
- 未绑定SIGINT处理函数:你的代码仅为SIGUSR1、SIGSEGV、SIGABRT等信号注册了处理逻辑,没有绑定SIGINT的处理函数,触发SIGINT(比如按Ctrl+C)时会执行系统默认的终止动作,直接退出程序。
signal函数语义缺陷:传统signal函数处理完一次信号后,会自动将该信号的处理方式重置为默认值,下一次触发同类型信号就会执行默认动作(绝大多数信号的默认动作都是终止程序),同时信号处理期间不会屏蔽同类型信号,容易出现竞态问题。建议替换为更稳定的sigaction函数,手动设置信号处理逻辑和屏蔽规则。- 异常类信号上下文未修复:SIGSEGV、SIGABRT属于程序异常触发的信号,如果是程序运行出错主动触发的这类信号,处理函数执行完后会回到触发异常的代码位置继续执行,错误没有修复的话会再次触发异常,最终导致程序终止。如果只是测试捕获逻辑,建议用
kill命令手动发送信号,不需要程序主动触发异常。
另外补充:SIGKILL、SIGSTOP是Linux内核规定的不可捕获、不可屏蔽、不可忽略的信号,绑定处理函数必然失败属于正常现象,无需额外处理。
问题2:无法触发SIGSEGV、SIGABRT等信号的解决方法
你的当前程序逻辑为无限循环sleep,没有任何会触发内存访问错误、主动终止的操作,自然不会主动触发对应信号,可以用两种方式触发:
- 手动发信号:先查询程序的进程ID,执行
ps aux | grep <你的编译后的程序名>获取pid,之后执行kill -11 <pid>触发SIGSEGV,kill -6 <pid>触发SIGABRT,kill -10 <pid>触发SIGUSR1,Ctrl+C触发SIGINT。 - 程序内加测试逻辑:可以在主循环中增加输入判断,比如输入1就访问空指针触发SIGSEGV,输入2就调用
abort()触发SIGABRT。
修正后的完整代码
#include<stdio.h> #include<time.h> #include<signal.h> #include<unistd.h> #include<stdlib.h> //bos501_hw_signals_handling_Linux void sig_handler(int signo) { time_t current_time; char* c_time_string; // 获取当前时间 current_time = time(NULL); // 转换为本地时间字符串 c_time_string = ctime(¤t_time); // 根据信号类型打印信息 if (signo == SIGINT) printf("received SIGINT\n ::Current time is %s", c_time_string); else if (signo == SIGUSR1) printf("received SIGUSR1\n ::Current time is %s", c_time_string); else if (signo == SIGSEGV) printf("received SIGSEGV\n ::Current time is %s", c_time_string); else if (signo == SIGABRT) printf("received SIGABRT\n ::Current time is %s", c_time_string); } int main(void) { struct sigaction sa; sa.sa_handler = sig_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); // 清空信号屏蔽集,处理期间仅屏蔽当前触发的信号 // 绑定SIGINT处理 if (sigaction(SIGINT, &sa, NULL) == SIG_ERR) printf("\ncan't catch SIGINT\n"); // 绑定SIGUSR1处理 if (sigaction(SIGUSR1, &sa, NULL) == SIG_ERR) printf("\ncan't catch SIGUSR1\n"); // 绑定SIGSEGV处理 if (sigaction(SIGSEGV, &sa, NULL) == SIG_ERR) printf("\ncan't catch SIGSEGV\n"); // 绑定SIGABRT处理 if (sigaction(SIGABRT, &sa, NULL) == SIG_ERR) printf("\ncan't catch SIGABRT\n"); // 以下两个信号无法捕获,打印提示属于正常现象 if (sigaction(SIGKILL, &sa, NULL) == SIG_ERR) printf("\ncan't catch SIGKILL\n"); if (sigaction(SIGSTOP, &sa, NULL) == SIG_ERR) printf("\ncan't catch SIGSTOP\n"); // 测试用主动触发逻辑,需要的话可以打开注释 // int input; // while (1) { // scanf("%d", &input); // if (input == 1) { // int *p = NULL; // *p = 1; // 触发SIGSEGV // } else if (input == 2) { // abort(); // 触发SIGABRT // } // sleep(1); // } // 原有等待逻辑 while (1) sleep(1); return 0; }
内容的提问来源于stack exchange,提问作者MaxXx _GAMER
相关产品推荐
相关产品推荐

