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

时间:2019-06-23 11:15:07

标签: c signals

我有一个简单的代码,该代码使用两个信号处理程序来处理“分段故障”信号。第一个在信号发生时起作用,在longjmp之后,我为该信号重新分配了处理程序,第二个则进行了处理。不幸的是,代码流没有到达必要的处理程序,我仍然遇到“分段错误”。

#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;
}

1 个答案:

答案 0 :(得分: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是一个很好的资源。它在signal handling上有一章很好。