为何循环产生 SIGSGEV 信号处理函数打印

[E][05-08 14:20:21924][sigsegv_handler :144] signo 11
[E][05-08 14:20:21925][_dump_handler_segv :92] stack start...
[E][05-08 14:20:21925][_dump_handler_segv :99] backtrace() returned 8 addresses
[E][05-08 14:20:21926][_dump_handler_segv :109]   [00] /mnt/mtd/sc2000_app() [0x15df32]
[E][05-08 14:20:21927][_dump_handler_segv :109]   [01] /mnt/mtd/sc2000_app() [0x15ef56]
[E][05-08 14:20:21927][_dump_handler_segv :109]   [02] /lib/libc.so.6(+0x25020) [0x76cf0020]
[E][05-08 14:20:21927][_dump_handler_segv :109]   [03] /lib/libpthread.so.0(+0x9dc2) [0x76f84dc2]
[E][05-08 14:20:21927][_dump_handler_segv :109]   [04] /lib/libpthread.so.0(pthread_cond_wait+0xd) [0x76f84e22]
[E][05-08 14:20:21927][_dump_handler_segv :109]   [05] /mnt/mtd/sc2000_app() [0x15b058]
[E][05-08 14:20:21927][_dump_handler_segv :109]   [06] /mnt/mtd/sc2000_app() [0x15bdc0]
[E][05-08 14:20:21928][_dump_handler_segv :109]   [07] /mnt/mtd/sc2000_app() [0x3a6976]
[E][05-08 14:20:21928][_dump_handler_segv :113] SIGSEGV happen...
[E][05-08 14:20:21928][sigsegv_handler :144] signo 11
[E][05-08 14:20:21928][_dump_handler_segv :92] stack start...
[E][05-08 14:20:21928][_dump_handler_segv :99] backtrace() returned 8 addresses
[E][05-08 14:20:21929][_dump_handler_segv :109]   [00] /mnt/mtd/sc2000_app() [0x15df32]
[E][05-08 14:20:21929][_dump_handler_segv :109]   [01] /mnt/mtd/sc2000_app() [0x15ef56]
[E][05-08 14:20:21929][_dump_handler_segv :109]   [02] /lib/libc.so.6(+0x25020) [0x76cf0020]
[E][05-08 14:20:21930][_dump_handler_segv :109]   [03] /lib/libpthread.so.0(+0x9dc2) [0x76f84dc2]
[E][05-08 14:20:21930][_dump_handler_segv :109]   [04] /lib/libpthread.so.0(pthread_cond_wait+0xd) [0x76f84e22]
[E][05-08 14:20:21930][_dump_handler_segv :109]   [05] /mnt/mtd/sc2000_app() [0x15b058]
[E][05-08 14:20:21930][_dump_handler_segv :109]   [06] /mnt/mtd/sc2000_app() [0x15bdc0]
[E][05-08 14:20:21930][_dump_handler_segv :109]   [07] /mnt/mtd/sc2000_app() [0x3a6976]
[E][05-08 14:20:21930][_dump_handler_segv :113] SIGSEGV happen...
[E][05-08 14:20:21931][sigsegv_handler :144] signo 11
[E][05-08 14:20:21931][_dump_handler_segv :92] stack start...
[E][05-08 14:20:21931][_dump_handler_segv :99] backtrace() returned 8 addresses
[E][05-08 14:20:21932][_dump_handler_segv :109]   [00] /mnt/mtd/sc2000_app() [0x15df32]
[E][05-08 14:20:21932][_dump_handler_segv :109]   [01] /mnt/mtd/sc2000_app() [0x15ef56]
[E][05-08 14:20:21932][_dump_handler_segv :109]   [02] /lib/libc.so.6(+0x25020) [0x76cf0020]
[E][05-08 14:20:21932][_dump_handler_segv :109]   [03] /lib/libpthread.so.0(+0x9dc2) [0x76f84dc2]
[E][05-08 14:20:21932][_dump_handler_segv :109]   [04] /lib/libpthread.so.0(pthread_cond_wait+0xd) [0x76f84e22]
[E][05-08 14:20:21932][_dump_handler_segv :109]   [05] /mnt/mtd/sc2000_app() [0x15b058]
[E][05-08 14:20:21933][_dump_handler_segv :109]   [06] /mnt/mtd/sc2000_app() [0x15bdc0]
[E][05-08 14:20:21933][_dump_handler_segv :109]   [07] /mnt/mtd/sc2000_app() [0x3a6976]
[E][05-08 14:20:21933][_dump_handler_segv :113] SIGSEGV happen...

进程产生 segmentation fault 错误,会收到 SIGSGEV 信号,肯定会执行到 SIGSGEV 信号处理函数_dump_handler_segv 。循环输出_dump_handler_segv函数里的打印,说明产生 segmentation fault 错误的代码被反复执行,程序才会不断的输出stack start..产生死循环。


信号处理函数的执行过程

当进程接收到信号会去执行重写的信号处理函数,如果信号处理函数当中没有退出程序或者转移程序的执行流(可以使用setjmp和longjmp实现),即调用函数正常返回。信号处理函数返回之后会重新执行信号发生位置的指令,也就是说哪条指令导致操作系统给进程发送信号,那条指令在信号处理函数返回的时候仍然会被执行,因此才看到了上面不停的输出结果,因为系统会不断的执行那条发生了 segmentation fault 的指令。

如何修正我们的代码,让程序不进入死循环,让程序能够得到我们的接管呢。有两种办法:

    一种是在信号处理函数当中进行一些逻辑处理之后,使用系统调用exit直接退出。
    另外一种使用setjmp和longjmp进行执行流的跳转。

1.直接使用exit退出

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void sig(int n)
{
    printf("直接在这里退出\n");
    _exit(1); // 使用系统调用直接退出
}

int main() {
    signal(SIGSEGV, sig);
    *(int*) NULL = 0;
    printf("结束\n"); // 这个打印不会输出
    return 0;
}

2.使用setjmp和longjmp进行执行流的跳转

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf env;

void sig(int n) {
  printf("准备回到主函数\n");
  longjmp(env, 1);
}

int main() {
    signal(SIGSEGV, sig);
    if(!setjmp(env)) {
        printf("产生段错误\n");
        *(int*) NULL = 0;
    }else {
        printf("回到了主函数\n");
    }
    return 0;
}

另外,如果没有重写 SIGSGEV 信号处理函数,将会使用 SIGSGEV 信号默认处理函数,再由内核输出段出错的回溯栈信息,通过dmesg可以查看。

最近更新

  1. TCP协议是安全的吗?

    2024-05-11 21:36:08       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-11 21:36:08       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-11 21:36:08       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-11 21:36:08       20 阅读

热门阅读

  1. Python 多进程和多线程在加速程序运行上的差别

    2024-05-11 21:36:08       12 阅读
  2. es 7.1.0 启用身份认证

    2024-05-11 21:36:08       10 阅读
  3. 送外卖面试回顾

    2024-05-11 21:36:08       12 阅读
  4. spring 创建bean的过程

    2024-05-11 21:36:08       10 阅读
  5. [ deepSpeed ] 单机单卡本地运行 & Docker运行

    2024-05-11 21:36:08       11 阅读
  6. Python 技巧:满意的逗号放置

    2024-05-11 21:36:08       13 阅读
  7. 类中的static成员的注意点

    2024-05-11 21:36:08       13 阅读
  8. 蓝桥杯备战9.拼数

    2024-05-11 21:36:08       14 阅读
  9. js 字符串截取,截取指定字符前面/后面的字符串

    2024-05-11 21:36:08       13 阅读