Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C handle signal SIGFPE and continue execution

Tags:

c

signals

I am trying to handle a SIGFPE signal but my program just crashes or runs forever. I HAVE to use signal() and not the other ones like sigaction().

So in my code I have:

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

void handler(int signum)
{
    // Do stuff here then return to execution below
}

int main()
{
    signal(SIGFPE, handler);

    int i, j;
    for(i = 0; i < 10; i++) 
    {
        // Call signal handler for SIGFPE
        j = i / 0;
    }

    printf("After for loop");

    return 0;
}

Basically, I want to go into the handler every time there is a division by 0. It should do whatever it needs to inside the handler() function then continue the next iteration of the loop.

This should also work for other signals that need to be handled. Any help would be appreciated.

like image 731
syy Avatar asked Jan 05 '23 09:01

syy


1 Answers

If you have to use signal to handle FPE or any other signal that you cause directly by invoking the CPU nonsense that causes it, it is only defined what happens if you either exit the program from the signal handler or use longjmp to get out.

Also note the exact placement of the restore functions, at the end of the computation branch but at the start of the handle branch.

Unfortunately, you can't use signal() like this at all; the second invocation causes the code to fall down. You must use sigaction if you intend to handle the signal more than once.

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

jmp_buf fpe;

void handler(int signum)
{
    // Do stuff here then return to execution below
    longjmp(fpe, 1);
}

int main()
{
    volatile int i, j;
    for(i = 0; i < 10; i++) 
    {
        // Call signal handler for SIGFPE
        struct sigaction act;
        struct sigaction oldact;
        memset(&act, 0, sizeof(act));
        act.sa_handler = handler;
        act.sa_flags = SA_NODEFER | SA_NOMASK;
        sigaction(SIGFPE, &act, &oldact);

        if (0 == setjmp(fpe))
        {
            j = i / 0;
            sigaction(SIGFPE, &oldact, &act);
        } else {
            sigaction(SIGFPE, &oldact, &act);
            /* handle SIGFPE */
        }
    }

    printf("After for loop");

    return 0;
}
like image 100
Joshua Avatar answered Jan 11 '23 19:01

Joshua