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 f77 example would have to be modified to run on SPARC V9 architectures (-xarch=v9 or v9a) 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:
demo% cat DetExcHan.f
EXTERNAL myhandler
REAL r / 14.2 /, s / 0.0 /
i = ieee_handler ('set', 'division', myhandler )
t = r/s
END
INTEGER FUNCTION myhandler(sig,code,context)
INTEGER sig, code, context(5)
CALL abort()
END
demo% f77 -silent DetExcHan.f
demo% a.out
abort: called
Abort (core dumped)
demo%
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 "f77_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 )
CALL abort()
END
demo% f77 -silent -g LocExcHan.F
demo% a.out
Signal 8 code 3 at hex address 11230
abort: called
Abort (core dumped)
demo%
In SPARC V9 environments, replace the INTEGER declarations within each STRUCTURE with INTEGER*8, and the i4 formats with i8.
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.