For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > January 2008 > catching SIGFPE signal









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author catching SIGFPE signal
subramanian100in@yahoo.com, India

2008-01-28, 8:23 am

I am using Redhat Enterprise Linux kernel 2.6.9 and gcc 3.4.3

consider the following program:

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

void signal_handler_SIGFPE(int signum)
{
printf("SIGFPE caught: %d\n", signum);
return;
}

void generate_signal(void)
{
int x = 100;
int y = 0;

int z = x / y;
}

int main(void)
{
if (signal(SIGFPE, signal_handler_SIGFPE) == SIG_ERR)
{
printf("Could not register signal_handler_SIGFPE\n");
exit(EXIT_FAILURE);
}

generate_signal();

int x = 0;
scanf("%d", &x);
printf("%d\n", x);

return EXIT_SUCCESS;
}

I compile the above program as
gcc -std=c99 -pedantic -Wall -Wextra 1.c

The output of the program is

SIGFPE caught: 8
Floating point exception

The output line "SIGFPE caught: 8" corresponds to the
signal_handler_SIGFPE() function. But after executing this handler,
control does not return to main(); but instead prints "Floating point
exception" and terminates the program.

Why doesn't the control go back to main() and continue processing ?
Does it mean that SIGFPE cannot be caught ?

Kindly clarify

Thanks
V.Subramanian
fnegroni

2008-01-28, 8:23 am

On my particular os (OS X Tiger), the signal handler remains installed
after being called by the trap of SIGFPE.
So instead of a program terminating abruptly, I get an infinite loop
printing the string SIGFPE caught: 8
On your system I believe the signal handler is reset after execution,
and after the first occurrence, the default behavior (core dump) takes
place.
I believe a floating point exception is generated by the FPU, and it
leaves the FPU in a state that must be cleared/reset in order to allow
any other floating point operation to be executed.
Look for a way to reset the FPU in your system.
ppi

2008-01-28, 7:24 pm


> void generate_signal(void)
> {
> int x = 100;
> int y = 0;
>
> int z = x / y;
>
> }


If your FPE signal is generated by something else than a kill/raise
call is usually fatal.
It is flagged as undefined behavior by the posix: "Integer division by
zero has undefined result"
So on some systems/processors it will be ok, on other ones it will
just crash the program.

Paulo
Rainer Temme

2008-01-28, 7:24 pm


The main problem with your code is ...

.... you return from the signal handler to the
location in the code where the signal is generated
(the division) ... since it is still a division by
zero, the same thing happens again.

From here, it depends on your system ...
your signal handler hasn't reinstalled the signal-routine
.... if the system resets handling to default, the program
will now be aborted ... if it leaves the setting of
the handler untouched, your signal-handler will be called
again and again. Under no circumstances will your code
return to the main function.

Your only chance to go to main is to use setjmp/longjmp or
to cure the division by setting y to a nonzero value before
returning from the signal-handler.

Scott Lurndal

2008-01-28, 7:24 pm

"subramanian100in@yahoo.com, India" <subramanian100in@yahoo.com> writes:
>I am using Redhat Enterprise Linux kernel 2.6.9 and gcc 3.4.3
>
>consider the following program:
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <signal.h>
>
>void signal_handler_SIGFPE(int signum)
>{
> printf("SIGFPE caught: %d\n", signum);
> return;
>}


>The output line "SIGFPE caught: 8" corresponds to the
>signal_handler_SIGFPE() function. But after executing this handler,
>control does not return to main(); but instead prints "Floating point
>exception" and terminates the program.
>
>Why doesn't the control go back to main() and continue processing ?
>Does it mean that SIGFPE cannot be caught ?
>


The signal handler is called with two additional parameters in
addition to the signal number. The second parameter is a pointer
to a siginfo_t structure and the third parameter describes the
state of the thread at the time of the exception (ucontext_t
datatype, although POSIX lists it as void *).

The state at the time of the exception is recorded into the
ucontext_t structure (e.g. instruction pointer, general registers,
etc). When you return from the signal handler, the state will
be restored and execution will continue.

For SIGFPE, the state recorded in the ucontext_t structure will
include the starting address of the divide instruction that
generates your SIGFPE. When you return from the signal handler,
that instruction will be re-executed, and as you didn't re-install
the signal handler, your application terminates. If you had reinstalled
your signal handler, or used sigaction(2) instead of signal(2), you'd
find your application in an infinite loop.

The possibilities for recovery are:

1) Interpret the instruction that failed and fixup its arguments
such that when returning from the signal handler the divide won't fail, or
2) Bump the 'next instruction' address in the ucontext_t to the
next instruction and skip the div (although this will cause
unspecified bad things to happen because the div didn't happen), or
3) Use longjmp/siglongjmp to return to a known good state.
4) Abort the application.

Only (3) and (4) are viable choices in my opinion, particularly if
portability is desired.

scott
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com