slmyers
slmyers

Reputation: 767

segfault handler for C only called once

I'm writing a program that scans the process memory and creates a memchunk structures to represent the accessibility of a block of memory. A side effect of this process is to learn how to handle signals, as there should be many segfaults over the course of this scan. So, I'm trying to cause many segfaults to learn about signals while also learning a bit about the virtual memory. This is compiled as a 32bit program on a linux platform. I make use of setjmp and longjmp in order to re-enter my program.

My problem is that my segfault handler is only called once, and then the default segfault handler -- the core dumping one -- is called on the next segfault.

Here is my handler:

static void hdl (int sig, siginfo_t *siginfo, void *unused){
    /* handler is called properly and can read curr_access */
    printf("-------------------\n");
    printf("handling segfault\n");
    printf("curr_access = %d\n", curr_access);
    printf("-----------------\n");
    switch(curr_access){
        case -1:
            longjmp(buf, 1);
            break;
        case 0:
            longjmp(buf, 2);
            break;
        default:
            printf("error in hdl\n");           
    }
}

Here is where I register it

void set_hndlr(){
    printf("------------------\n");
    printf("setting handler\n");
    printf("-----------------\n");
    /* setting up signal handler */
    struct sigaction sa;

    sa.sa_flags = SA_SIGINFO;
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = hdl;
    if (sigaction(SIGSEGV, &sa, NULL) == -1)
        printf("error setting segfault hanld");
}

here is where I "test" a memory location:

switch(jmp_code){
    /* we haven't gone through testing yet */
    case 0:
        test_boolean = 1; 
        break;
    /* we've gone through testing and we segfaulted at read */
    case 1:
        test_boolean = 0;
        curr_access = -1;
        break;
    /* we've gone through testing and we segfaulted at write */
    case 2:
        test_boolean = 0;
        curr_access = 0;
        break;
    /* if we reach here then there is an error in program logic */
    default:
        printf("error in programming logic regaurding jmp\n");
        exit(-2);
}
if(1 == test_boolean){
    /* not accessible */
    curr_access = -1;
    printf("testing read\n");
    /*test read */
    curr_cont = *curr_addr;
    curr_access = 0;
    printf("readable\n");
    /*test write */
    *curr_addr = curr_cont;
    curr_access = 1;
    printf("read/write\n");
}

Here is some example output:

setting handler

curr_addr = (nil)
jmp_code = 0
testing read

handling segfault
curr_access = -1

jmp_code = 1

base[0].RW = -1
base[0].length = 4096
base[0].start = (nil)

curr_addr = 0x1000
jmp_code = 0
testing read
Segmentation fault (core dumped)

It's strange that I can handle one segfault just fine, but then it wont handle again. I would really appreciate any help.

Upvotes: 0

Views: 348

Answers (1)

Karthikeyan.R.S
Karthikeyan.R.S

Reputation: 4041

In some of the systems, it does not support the re-assignig of singal handler. we have to re assign the handle after the calling of that function_handler.

Unreliable Signals

One problem with these early versions is that the action for a signal was reset to its default each time the signal occurred.

 int sig_int();
 ...
 signal(SIGINT, sig_int);
 ...
 sig_int()
 {
    signal(SIGINT, sig_int);
    ...
 }

Upvotes: 2

Related Questions