Hi,

I have a problem with signal handler algorithm in linux. My code is hanging ( It is continuously looping inside the signal handler) . I am pasting my code here...

any help is appreciated

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

struct sigaction oldHandler;

void myHandler(int sig,  siginfo_t *siginfo, void *context) {
// if i have not written any code inside this function, the program will give a feel of hang( this functions is getting continuously called
        if(siginfo->si_code == SEGV_MAPERR)
        {
                write(1,"address not mapped to object",strlen("address not mapped to object"));
        }
        else if (siginfo->si_code == SEGV_ACCERR)
        {
                write(1,"invalid permissions for mapped object",strlen("invalid permissions for mapped object"));
        }

       write(1,"\n",1);

 //        exit(0); if this exit(0) is not present, program will get continuous calls to this signal handler
        return;
}

int main(int argc, char *argv[]) {

    /* Install mySignalHandler for SIGSEGV */
    struct sigaction sigAct;
    int              status = 0;
    char *addr = NULL;

    sigAct.sa_handler   = 0;
    sigAct.sa_sigaction = myHandler;
    sigfillset(&sigAct.sa_mask);
    sigAct.sa_flags = SA_SIGINFO;

    status = sigaction(SIGSEGV, &sigAct, &oldHandler);
    if (status != 0) {
        perror("Failed to install handler for signal SIGSEGV");
        exit(1);
    }
#if 1
    /* This will invoke the signal handler */
// addr = malloc(strlen("Hello"));
     strcpy(addr,"Hello");
    printf("%s\n",addr);

#endif
        printf("Returning from main\n");
    return 0;
}

Dani AI

Generated

Short, practical explanation and a safe pattern to fix the loop

The handler keeps getting invoked because returning from a SIGSEGV handler normally resumes execution at the instruction that faulted. If that instruction still reads/writes invalid memory you get SIGSEGV again, so the handler appears to “loop.” That is why the usual choices are: fix the bug that caused the fault, terminate the process, or deliberately restore the default action and re-raise the signal so the kernel performs the default termination (and optionally produces a core). (man7.org)

Keep the handler tiny and use only async-signal-safe functions. Avoid stdio, malloc, exit(), etc.; prefer write(2), sigaction(), raise()/kill(), _exit() or abort() from inside a handler. Also avoid calling complex helpers like printf or functions that may take locks. A minimal, safe pattern that prints a static message then hands control back to the kernel is shown below:

void handler(int sig, siginfo_t *si, void *uc) {
    const char msg[] = "segfault (faulting address)\n";
    write(STDERR_FILENO, msg, sizeof msg - 1);

    struct sigaction sa;
    memset(&sa, 0, sizeof sa);
    sa.sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);
    sigaction(sig, &sa, NULL);

    raise(sig);    /* re-deliver so kernel does the default */
}

Details and practical tips

  • Initialize your sigaction struct (memset or designated init) and use sa_sigaction with SA_SIGINFO if you need siginfo; consider SA_RESETHAND to auto-reset to default. (man7.org)
  • If a segfault is due to a stack overflow, install an alternate stack with sigaltstack and use SA_ONSTACK. (man7.org)
  • If you think about using sigsetjmp/siglongjmp to recover, be cautious: POSIX allows them but there are portability and undefined-behavior caveats if the handler interrupted non-async-signal-safe code. Use only with full understanding of the constraints. (manpages.opensuse.org)
  • For the “only-call-safe-functions” rule and the canonical list of async-signal-safe calls, see the signal-safety reference. (man7.org)

Thanks to for pointing toward restoring the default action; the above expands that advice into a safe, minimal pattern and additional troubleshooting notes for ’s NULL-addr strcpy case (allocate/avoid copying to NULL and include the proper headers).

Recommended Answers

All 2 Replies

Hi Sree_ec,
That is how this particular signal works. Check out this . After a "Segmentation fault", it is not possible for the program to continue and it will still continue to handle the signal. This step is causing the loop.
The text says that - "The handler should end by specifying the default action for the signal that happened and then reraising it; this will cause the program to terminate with that signal, as if it had not had a handler".
When you were putting exit(0), you were invariable doing the same thing.
However, the proper way to do is - (snippet of the code)

if(siginfo->si_code == SEGV_MAPERR)
        {
                write(1,"address not mapped to object",strlen("address not mapped to object"));
                 sigaction(SIGSEGV, &oldHandler, NULL);
        }

That should fix it !

Hi Sree_ec,
That is how this particular signal works. Check out this . After a "Segmentation fault", it is not possible for the program to continue and it will still continue to handle the signal. This step is causing the loop.
The text says that - "The handler should end by specifying the default action for the signal that happened and then reraising it; this will cause the program to terminate with that signal, as if it had not had a handler".
When you were putting exit(0), you were invariable doing the same thing.
However, the proper way to do is - (snippet of the code)

if(siginfo->si_code == SEGV_MAPERR)
        {
                write(1,"address not mapped to object",strlen("address not mapped to object"));
                 sigaction(SIGSEGV, &oldHandler, NULL);
        }

That should fix it !

That was a good piece of information you shared... :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.