Question

I am trying to handle SIGSEGV signal from my code. I have written the following code in C under Fedora 15. My problem is that the signal handler is not getting called for the second segmentation fault. Can anybody kindly point out what i am doing wrong.

typedef struct _ST_DEMO
{
    int m_iUnused;

    _ST_DEMO()
    {
        m_iUnused = 0;
    }
} ST_DEMO;

jmp_buf ex_buf__;

static void sig_hdl (int sig, siginfo_t *siginfo, void *context)
{
    cout<<"Inside Signal Handler."<<endl;
    longjmp(ex_buf__, 1);
}

int main (int argc, char *argv[])
{
    ST_DEMO* pStDemo = 0;
    struct sigaction act;

    memset (&act, '\0', sizeof(act));

    /* Use the sa_sigaction field because the handles has two additional parameters */
    act.sa_sigaction = &sig_hdl;

    /* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
    act.sa_flags = SA_SIGINFO;

    if (sigaction(SIGSEGV, &act, NULL) < 0)
    {
        perror ("sigaction");
        return 1;
    }

    if(!setjmp(ex_buf__))
    {
        cout<<"Before First Seg Fault."<<endl;
        cout<<pStDemo->m_iUnused<<endl;
    }
    else
    {
        cout<<"After jump."<<endl;
    }

    cout<<"Before Second Seg Fault."<<endl;
    cout<<pStDemo->m_iUnused<<endl;

    while(1)
    {
        sleep(1);
    }

    return 0;
}
Was it helpful?

Solution

Your longjmp will cause you to jump to the location, but you will not have returned from the signal handler. This means that the signal is still blocked (this is the default behavior for signals, they are masked until you have returned from the signal handler).

You can fix this by indicating that you want the signal to occur again by clearing the signal mask in your handler before longjmp.

  • Use the SA_NODEFER flag in act.sa_flags to prevent it from being masked in the first place.
  • Use the siglongjmp/sigsetjmp functions, which saves the mask for you

Or

  • Call sigprocmask either before or after the longjmp to unmask it yourself.

A warning: This is a very dangerous thing to do (catch SIGSEGV, and then longjmp out of the signal handler) and it will be almost impossible to do anything useful with it.

If the memory access error occurs in any function that is not async signal safe and reentrant you will not be able to continue in any kind of sane way anyway.

But since there are multiple similar questions on the site I guess this is some kind of exercise.

Related question: Catching Segmentation Violations and Getting on with Life

Also useful

Longjmp out of signal handler? longjmp() from signal handler

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top