无法第二次重新分配信号处理程序

Unable to reassign signal handler second time

我有一个简单的代码,它使用两个信号处理程序来处理 "Segmentation fault" 信号。第一个在信号发生时起作用,在 longjmp 之后,我为该信号重新分配处理程序和第二个。不幸的是,代码流没有到达必要的处理程序,我仍然得到 "Segmentation fault"。

#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

int i;
int ci;

jmp_buf m_env_buffer;
jmp_buf max_env_buffer;

void handler(int signum){
    printf("sigsegv on i:[%d]", i);
    ci = (++i);
    longjmp(m_env_buffer,1);
}

void top_handler(int signum){
    printf("sigsegv on max i:[%d]", i);
    longjmp(max_env_buffer,10);
}

int main(void) {
    signal(SIGSEGV, handler);
    char * pstart = "loremipsum";

    int m_cell = 0;
    char m_cell_v;

    int point;

    point = setjmp(m_env_buffer);
    if(point == 0){
            for(i=0; ;i--){
                    m_cell_v = pstart[i];
            }
    }

    //this wasn't invoked
    signal(SIGSEGV, top_handler);
    point = setjmp(max_env_buffer);
    if(point == 0){
            for(i=ci; ;i++){
                    char cur = pstart[i];
                    if(cur==10)
                            printf("\n");
                    printf("%c",cur);
            }
    }
    puts("finish");
    return 0;
}

signal() 不应使用。它具有不可靠的语义。在您的系统上,默认操作(终止)在收到第二个 SIGSEGV 时执行。第二次调用 signal() 实际上没有任何效果。

您应该改用 sigaction()。在您的情况下,您可以使用以下函数代替 signal():

void set_signal (int signum, void (*handler)(int))
{
    struct sigaction act;

    act.sa_handler = handler;
    sigemptyset (&act.sa_mask);
    act.sa_flags = SA_NODEFER;
    act.sa_restorer = NULL;

    sigaction (signum, &act, NULL);
}

以后,请阅读您可以使用的文档。 glibc manual. It has a good chapter on signal handling 是一个很好的资源。