Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Aug 1998 09:51:57 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        current@FreeBSD.ORG, luoqi@watermarkgroup.com, shocking@prth.pgs.com
Subject:   Re:  Floating Point Exceptions, signal handlers & subsequent ops
Message-ID:  <199808252351.JAA32306@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>> I've noticed in one of my applications that the first FP operation after 
>> return from a caught SIGFPE is invalid. I have a signal handler installed that 

This is normal.  Returning from a SIGFPE handler gives explicitly undefined
behaviour in ANSI C.  It gives various bad behaviours for FreeBSD on i386's:

1) if the SIGFPE was for integer division by zero, then the division will
   be restarted and the SIGFPE will be repeated endlessly.

2) if the SIGFPE was for an FP  operation, then the FP operatation will be
   restarted.  The kernel has cleared the trap-pending flag before delivering
   the SIGFPE to the application, and on i386's traps are delivered to the
   kernel on the the first non-control FP operation after the one that
   caused the exception, so it is certain that the restarted FP operation
   won't trap; it may cause an exception which will be delivered to the
   kernel on the next non-control FP operation.

>> just prints out some basic info (like "SIGFPE caught"). The first FP op after 
>> this (in my case, converting a long to a double) just gives garbage. Repeat 

Long to double conversion actually takes 4 or 5 FP operations.  long to
double conversion will only trap on i386's for FP stack overflow.  It's
normal for botched signal handling to leave junk on the stack.  E.g.,
faddp normally pops one operand, but if it causes an exception then it
doesn't change the stack.

>Your SIGFPE handler has to restore the FP register stack top, and this is
>no easy job to do, you have to handle each exception type differently. It's
>not FreeBSD's problem, rather a stupid design on intel's part.

It has to do much more than that if it wants to return:

1) First decide if the exception is for FP or integer division by 0, by
   looking at the trap code.  FreeBSD's support for trap codes is
   primitive and unportable (see <machine/trap.h>), but probably good
   enough to distinguish integer division by zero.

2) Handle the easy case of integer division by zero (if this can happen).
   Just modify the operands so that it doesn't happen, or advance the
   program counter and supply a result.

3) Handle all cases of FP exceptions that can happen, much like the
   integer division case except there are potentially thousands more
   cases.  You basically need an FP emulator.  Changing the stack top is
   not sufficient.  You also need to supply a result for the exception
   operation and leave it at the approriate place on the stack.  The FPU
   doesn't generate a default result for trapped exceptions, presumably
   because leaving it on the stack would usually clobber an operand,
   making it impossible for smart SIGFPE handlers (which no one writes
   :-) to do a complete fixup.

The right way to handle this problem is to avoid it, either by not
trapping FP exceptions (this causes different problems), or by longjmping
out of the SIGFPE handler (set up the longjmp before each FP operation
that may trap), or by checking operands to ensure that there are no traps.

Bruce

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



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