I expect the program below to run succesfully to completion (and exit with a 0 status). On both AMD 64 and Intel EM64T (but not on x86, IA64) the program abends during the second division, despite the signal handler. $ /lib64/tls/libc.so.6 && cat ~/tmp/t.c && gcc ~/tmp/t.c && ./a.out GNU C Library stable release version 2.3.4, by Roland McGrath et al. Copyright (C) 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 3.4.4 20050721 (Red Hat 3.4.4-2). Compiled on a Linux 2.4.20 system on 2005-08-19. Available extensions: GNU libio by Per Bothner crypt add-on version 2.1 by Michael Glad and others Native POSIX Threads Library by Ulrich Drepper et al The C stubs add-on version 2.1.2. GNU Libidn by Simon Josefsson BIND-8.2.3-T5B NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk Thread-local storage support included. For bug reporting instructions, please see: <http://www.gnu.org/software/libc/bugs.html>. #include <setjmp.h> #include <signal.h> #include <stdio.h> jmp_buf env; volatile sig_atomic_t traps; void handler (int signo) { ++traps; longjmp (env, 1); } volatile int zero; volatile int one; volatile int result; int main () { signal (SIGFPE, handler); ++one; if (0 == setjmp (env)) { printf ("first division\n"); result = one / zero; } else { signal (SIGFPE, handler); printf ("second division\n"); if (0 == setjmp (env)) { result = one / zero; } } printf ("%d traps\n", traps); } first division second division Floating point exception
FWIW, it might be helpful to note that when compiled with Sun C++ 5.8 on Solaris 10/AMD 64, the same program behaves as expected: $ uname -rvi && cc -V ~/tmp/t.c && ./a.out 5.10 Generic_118844-20 i86pc cc: Sun C 5.8 2005/10/13 acomp: Sun C 5.8 2005/10/13 ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.481 first division second division 2 traps
This is a kernel issue. You are generating a SIGFPE while it is blocked. Use sigsetjmp/siglongjmp instead.