[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
questions re SIGFPE
- To: tech_(_at_)_openbsd_(_dot_)_org
- Subject: questions re SIGFPE
- From: Jon Bernard <jonbernard_(_at_)_pobox_(_dot_)_com>
- Date: Wed, 26 Jun 2002 15:43:54 -0500
I'm working on an x86 port of Standard ML, ie, sml-nj, and I've run into
trouble dealing with signals.
Specifically, what signals and signal codes are generated by integer divide by
zero and overflow errors?
After looking at <sys/siginfo.h> and the FreeBSD and NetBSD code below (the
result of applying the patches from the FreeBSD and NetBSD ports, which seem
actively maintained, so I'm assuming it works), I tried
# define INT_DIVZERO(s, c) (((s) == SIGFPE) && ((c) == FPE_INTDIV))
# define INT_OVFLW(s, c) (((s) == SIGFPE) && ((c) == FPE_INTOVF))
(INT_DIVZERO(s,c) and INT_OVFLW(s,c) take (signal,code) as arguments.)
but the compile eventually fails with an "unexpected fault, signal = 8, code =
0" message.
Using either of
# define INT_DIVZERO(s, c) (((s) == SIGFPE) && ((c) == 0))
# define INT_OVFLW(s, c) (((s) == SIGFPE) && ((c) == FPE_INTOVF))
# define INT_DIVZERO(s, c) (((s) == SIGFPE)
# define INT_OVFLW(s, c) (((s) == SIGFPE) && ((c) == FPE_INTOVF))
gets me past that bump, but seems to result in the masking of an overflow
error that stops the build a bit later:
Fault handler: sig = 8, code = 0, inML = 1
uncaught exception divide by zero
raised at: <file wrapping.sml.bin>
translate/wrapping.sml:119.10
Everything builds with
/* always tests negative? */
# define INT_DIVZERO(s, c) (((s) == SIGFPE) && ((c) == FPE_INTDIV)
/* c always 0? */
# define INT_OVFLW(s, c) (((s) == SIGFPE) && ((c) == 0))
but then, as might be expected, sml interprets divide by zero errors as
overflows (it doesn't under Solaris or Linux, ie, the sml developers don't
seem to intend it to).
Signal-handling code is completely new to me, so any help is much appreciated.
Thanks,
Jon
Free and NetBSD code fragments:
# elif defined(OPSYS_FREEBSD)
/** x86, FreeBSD **/
# define SIG_FAULT1 SIGFPE
# define INT_DIVZERO(s, c) (((s) == SIGFPE) && ((c) == FPE_INTDIV))
# define INT_OVFLW(s, c) (((s) == SIGFPE) && ((c) == FPE_INTOVF))
# define SIG_GetCode(info, scp) (info)
# define SIG_GetPC(scp) ((scp)->sc_pc)
# define SIG_SetPC(scp, addr) { (scp)->sc_pc = (long)(addr); }
# define SIG_ZeroLimitPtr(scp) { ML_X86Frame[LIMITPTR_X86OFFSET] = 0; }
typedef void SigReturn_t;
# elif defined(OPSYS_NETBSD)
/** x86, NetBSD **/
/* NetBSD (including versions 1.0 and 1.1) generates SIGBUS rather
than SIGFPE for overflows. The real fix is a trivial change to
kernel sources, which has already been reported (NetBSD internal
problem identification "port-i386/1833").
If you want to fix this on your NetBSD system. Edit machdep.c in
directory /sys/arch/i386/i386, and find the line
setgate(&idt[ 4], &IDTVEC(ofl), 0, SDT_SYS386TGT, SEL_KPL);
Change SEL_KPL to SEL_UPL. With SEL_KPL, the int overflow trap is
not accessible at user level, and a protection fault occurs instead
(thus the seg fault). SEL_UPL will allow user processes to generate
this trap.
For the change to take effect, recompile your kernel, install it
and reboot. */
# define SIG_FAULT1 SIGFPE
# define SIG_FAULT2 SIGBUS
# define INT_DIVZERO(s, c) 0
# define INT_OVFLW(s, c) (((s) == SIGFPE) || ((s) == SIGBUS))
# define SIG_GetCode(info, scp) (info)
# define SIG_GetPC(scp) ((scp)->sc_pc)
# define SIG_SetPC(scp, addr) { (scp)->sc_pc = (long)(addr); }
# define SIG_ZeroLimitPtr(scp) { ML_X86Frame[LIMITPTR_X86OFFSET] = 0; }
typedef void SigReturn_t;
Visit your host, monkey.org