Typical concerns about IEEE exceptions are:
What happens when an exception occurs?
How do I use ieee_handler() to establish a user function as an exception handler?
How do I write a function that can be used as an exception handler?
How do I locate the exception—where did it occur?
Exception trapping to a user routine begins with the system generating a signal on a floating-point exception. The standard UNIX name for signal: floating-point exception is SIGFPE. The default situation on SPARC platforms is not to generate a SIGFPE when an exception occurs. For the system to generate a SIGFPE, exception trapping must first be enabled, usually by a call to ieee_handler().
To establish a function as an exception handler, pass the name of the function to ieee_handler(), together with the name of the exception to watch for and the action to take. Once you establish a handler, a SIGFPE signal is generated whenever the particular floating-point exception occurs, and the specified function is called.
The form for invoking ieee_handler() is shown in the following table:
Table 6–4 Arguments for ieee_handler( action , exception , handler)
Argument |
Type |
Possible Values |
---|---|---|
action |
character |
get, set, or clear |
exception |
character |
invalid, division, overflow, underflow, or inexact |
handler |
Function name |
The name of the user handler function or SIGFPE_DEFAULT, SIGFPE_IGNORE, or SIGFPE_ABORT |
Return value |
integer |
0 =OK |
A Fortran 95 routine compiled with f95 that calls ieee_handler() should also declare:
#include ’floatingpoint.h’
The special arguments SIGFPE_DEFAULT, SIGFPE_IGNORE, and SIGFPE_ABORT are defined in these include files and can be used to change the behavior of the program for a specific exception:
SIGFPE_DEFAULT or SIGFPE_IGNORE |
No action taken when the specified exception occurs. |
SIGFPE_ABORT |
Program aborts, possibly with dump file, on exception. |
The actions your exception handler takes are up to you. However, the routine must be an integer function with three arguments specified as shown:
handler_name( sig, sip, uap )
handler_name is the name of the integer function.
sig is an integer.
sip is a record that has the structure siginfo.
uap is not used.
Example: An exception handler function:
INTEGER FUNCTION hand( sig, sip, uap ) INTEGER sig, location STRUCTURE /fault/ INTEGER address INTEGER trapno END STRUCTURE STRUCTURE /siginfo/ INTEGER si_signo INTEGER si_code INTEGER si_errno RECORD /fault/ fault END STRUCTURE RECORD /siginfo/ sip location = sip.fault.address ... actions you take ... END |
This example would have to be modified to run on 64 bit SPARC architectures by replacing all INTEGER declarations within each STRUCTURE with INTEGER*8.
If the handler routine enabled by ieee_handler() is in Fortran as shown in the example, the routine should not make any reference to its first argument (sig). This first argument is passed by value to the routine and can only be referenced as loc(sig). The value is the signal number.
The following examples show how to create handler routines to detect floating-point exceptions.
Example: Detect exception and abort:
SIGFPE is generated whenever that floating-point exception occurs. When the SIGFPE is detected, control passes to the myhandler function, which immediately aborts. Compile with -g and use dbx to find the location of the exception.
Example: Locate an exception (print address) and abort:
demo% cat LocExcHan.F #include "floatingpoint.h" EXTERNAL Exhandler INTEGER Exhandler, i, ieee_handler REAL:: r = 14.2 , s = 0.0 , t C Detect division by zero i = ieee_handler( ’set’, ’division’, Exhandler ) t = r/s END INTEGER FUNCTION Exhandler( sig, sip, uap) INTEGER sig STRUCTURE /fault/ INTEGER address END STRUCTURE STRUCTURE /siginfo/ INTEGER si_signo INTEGER si_code INTEGER si_errno RECORD /fault/ fault END STRUCTURE RECORD /siginfo/ sip WRITE (*,10) sip.si_signo, sip.si_code, sip.fault.address 10 FORMAT(’Signal ’,i4,’ code ’,i4,’ at hex address ’, Z8 ) Exhandler=1 CALL abort() END demo% f95 -g LocExcHan.F demo% a.out Signal 8 code 3 at hex address 11230 Abort demo% |
In 64–bit SPARC environments, replace the INTEGER declarations within each STRUCTURE with INTEGER*8, and the i4 formats with i8. (Note that this example relies on extensions to the f95 compiler to accept VAX Fortran STRUCTURE statements.)
In most cases, knowing the actual address of the exception is of little use, except with dbx:
demo% dbx a.out (dbx) stopi at 0x11230 Set breakpoint at address (2) stopi at &MAIN+0x68 (dbx) run Run program Running: a.out (process id 18803) stopped in MAIN at 0x11230 MAIN+0x68: fdivs %f3, %f2, %f2 (dbx) where Shows the line number of the exception =>[1] MAIN(), line 7 in "LocExcHan.F" (dbx) list 7 Displays the source code line 7 t = r/s (dbx) cont Continue after breakpoint, enter handler routine Signal 8 code 3 at hex address 11230 abort: called signal ABRT (Abort) in _kill at 0xef6e18a4 _kill+0x8: bgeu _kill+0x30 Current function is exhandler 24 CALL abort() (dbx) quit demo% |
Of course, there are easier ways to determine the source line that caused the error. However, this example does serve to show the basics of exception handling.