Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Sep 1996 23:23:30 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        candy@fct.kgc.co.jp, hackers@freebsd.org
Subject:   Re: SIGFPE and signal(3)
Message-ID:  <199609211323.XAA18730@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>Hello.  Next program never ends.  Why?  And how can I handle SIGFPE?

On the i386, division instructions that trap are restarted if the signal
handler just returns (use gdb to see this).

longjmp() in the signal handler is the only simple way to escape from
the trap.  The main code should be something like:

	if (setjmp(jb))
		fix_up_or_give_up();
	else
		code_that_might_trap();

If there is a large amount of code that might trap, then you won't have
much idea where the problem occured, so fixing it is impractical, but
giving up might be reasonable.

Returning from the SIGFPE handler for a floating point trap is also
usually wrong, but may sort of work on the i386 because of the different
way that the FPU works and more possibilities for kernel trap handling.
FPU instructions that trap are also restarted; however, kernels normally
clear the FPU exception bits before calling the signal handler, and
FPU instructions that cause an exception don't trap until the next FPU
instruction after the one that caused the exception.  Thus execution
normally proceeds beyond the instruction that caused the original trap.
The FPU state is undefined after a SIGFPE, unless the SIGFPE handler
calls longjmp(), when (in FreeBSD) it the state is restored to almost the
one at the time of the corresponding setjmp().  (The state is actually
something like: in -current, all registers are empty, which is usually the
wrong state for returning from the signal handler with; in my version,
the state is the same as when the trap occured except the exception mask
is cleared.)

Bruce

>--------------------
>#include <signal.h>
>#include <stdio.h>
>
>void
>f(int x)
>{
>	fprintf(stderr, "x = %d\n", x);
>}
>
>int x = 1, y = 0;
>
>main()
>{
>	int z;
>	signal(SIGFPE, f);
>	printf("start\n");
>	z = x / y;
>	printf("%d\n", z);
>}
>-------------------



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199609211323.XAA18730>