Reputation: 1750
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
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
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
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