Bug #10546
openfloating point exception handlers infinite loop if trap comes from SSE/SSE2
0%
Description
If we get a SIGFPU from SSE/SSE2 code, and we handle it (even with SIGFPU_IGNORE) we infinite loop.
This seems to be because the pc remains on the trapping instruction, and we go back and run it again.
When we're using the x87 FPU, the pc is on an fstpl when we trap, and coming through again is fine.
// cc -ftrap=division -xarch=386 fpe.c -o fpe // cc -ftrap=division -xarch=sse2 fpe.c -o fpesse // cc -m64 -ftrap=division fpe.c -o fpe64 #include <stdio.h> #include <floatingpoint.h> #include <sys/ieeefp.h> #include <signal.h> #include <ucontext.h> void handle_division(int sig, siginfo_t *info, ucontext_t *ctx) { printf("division: si_addr=%p pc=%p\n", info->si_addr, ctx->uc_mcontext.gregs[REG_PC]); } int main(int argc, char **argv) { sigfpe(FPE_FLTDIV, handle_division); printf("%f\n", 10.0 / 0); }
Will demonstrate the problem (we use Sun cc for -ftrap, otherwise you have to unmask the exception by hand).
on i386/x87 we take the signal here:
mdb: stop on SIGFPE mdb: target stopped at: main+0x24: fstpl (%esp)
on i386/sse and amd64 we take the signal here:
mdb: stop on SIGFPE mdb: target stopped at: main+0x1d: divsd 0x8050be0,%xmm0
and appear to return to execute this again when the handler completes, I say "appear to" because a breakpoint there really pisses off mdb, who is no longer speaking to me at this juncture.
Updated by Rich Lowe about 3 years ago
So the manuals state that SIMD exceptions are immediate, and presume that the handler will either fix any operands and then allow the instruction to complete or it will abort. Perhaps that means the behaviour here is expected, even if weird when it comes down to the precise instruction sequence chosen by the compiler.
I think that this even makes mdb's behaviour somewhat defensible, if not in context.