Vishal Sharma
Vishal Sharma

Reputation: 1750

Signal handling(SIGFPE)

In the below code:

#include <unistd.h>
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
using namespace std;
void signal_callback_handler(int signum)

{
printf ("Caught signal %d\n", signum);
exit (signum);
}

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

int a=4;
int b=55444;

while (1)
{
printf ("Program processing stuff here.\n");
cout<<b/a;
a--;
b++;
sleep (1);
}
return EXIT_SUCCESS;
}

When the variable 'a' becomes 0, the program gets the SIGFPE signal from the OS and the program terminates with the message:"Caught signal 8". However, if I comment out ,the "exit(signum);" line in the 'signal_callback_handler' definition, the program keeps on running endlessly and keeps on printing "Caught Signal 8" statement on the screen. Why does this happen? Why is this signal somehow getting generated repeatedly?

I was expecting that the signal will be generated once, and after going through the signal handler function, the program will resume after the 'cout << b/a' statement and then the program will continue normally.However, since this is not happening, how can I achieve my objective?

Upvotes: 1

Views: 3408

Answers (3)

llllllllll
llllllllll

Reputation: 16404

In x86, this is because divide error is a fault, which means when control flow returns, the program counter (%rip) will point to the address of the previous faulty code, not the next instruction.

A normal strategy of handling SIGFPE is using setjmp to jump to a recoverable state from the signal handler.

A simple example from your own code ( by the way, never use printf() in signal handler ):

#include <setjmp.h>
using namespace std;

jmp_buf excep;

void signal_callback_handler(int signum)

{
longjmp(excep, 1);
}

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

int a=4;
int b=55444;

    while (1)
    {
        printf ("Program processing stuff here.\n");
        if ( setjmp(excep) == 0 ) {
            // normal control flow
            cout<<b/a;
        }
        else {
            // from longjmp
            printf("Exception caught\n");
        }
        a--;
        b++;
        sleep (1);
    }
return EXIT_SUCCESS;
}

Upvotes: 1

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

It is recommended for signal like SIGILL or SIGFPE to stop the execution and not try to recover.

POSIX says:

The behavior of a process is undefined after it returns normally from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(), sigqueue(), or raise().

In many implementations, when the handler finishes the instruction that generated the exception is restarted which generated a new SIGFPE, etc.

Upvotes: 2

BunnyDhaliwal
BunnyDhaliwal

Reputation: 100

I think gcc creates a return point into the while loop for you from the signal handler and it keeps jumping in and out of the signal handler. You can try to use no_return attribute for gcc to make sure your program does not return into the while loop and you can continue your program by calling some other function.

Upvotes: 1

Related Questions