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

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(&current_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 03:42:03