Pushpendra
Pushpendra

Reputation: 459

Segmentation fault in segmentation fault handler

I have encountered in a problem where segmentation fault is being raised within segmentation fault handler. Although I have already fixed the actual issue, but still I am confused that why below program is not going in infinite loop:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void C() 
{
    int *p = NULL;
    *p = 3;
}

void B() 
{
    C();
}

void segfault_sigaction(int signal, siginfo_t *si, void *arg)
{
    printf("Came in sigaction.\n");
    //if(si)
        //printf("Caught segfault at address %p\n", si->si_addr);
    B();
}
int main(void)
{
    struct sigaction sa; 

    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = segfault_sigaction;
    sa.sa_flags   = SA_SIGINFO;

    sigaction(SIGSEGV, &sa, NULL);

    segfault_sigaction(0, NULL, NULL);

    return 0;
}

Output of the above code is as below:

Came in sigaction.
Came in sigaction.
Segmentation fault (core dumped)

In the comments of this similar post: Segmentation fault within segmentation fault handler some folks have commented that it should go in infinite loop but it's not the current behavior. Can someone explain to me what's happening ??

Upvotes: 3

Views: 941

Answers (1)

M.M
M.M

Reputation: 141534

You are raising a signal while in a signal handler. The POSIX standard says:

[table of safe functions]

All functions not in the above table are considered to be unsafe with respect to signals. In the presence of signals, all functions defined by this volume of IEEE Std 1003.1-2001 shall behave as defined when called from or interrupted by a signal-catching function, with a single exception: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined.

void C() is an unsafe function because it is not in the list of safe functions, therefore having it raise a signal causes undefined behaviour. (I think it is also intended to mean that raising a signal from the signal handler function causes UB too, although the wording is unclear).

Being undefined behaviour, you cannot rely on an infinite loop or any other such behaviour.

Other points:

  • Dereferencing null is undefined behaviour and is not guaranteed to generate a SIGSEGV in the first place.
  • Calling printf in the signal handler is undefined behaviour because that is not one of the safe functions from the table either.
  • It is also UB to return from a signal handler for SIGSEGV. The only portable way to get out of the signal handler is to abort the process with a call such as exit.

Upvotes: 3

Related Questions