As I commented, most signals are OS specific. For Linux, read carefully signal(7). You forgot a \n
inside your printf
(usually, you'll be lucky enough to see something work in your code, but read all my answer). And in principle you should not call printf
(which is not an async-signal-safe function, you should use directly and only write(2) inside) from your signal handler.
What probably is happening is (ignoring the undefined behavior posed by wrongly using printf
inside the signal handler) is that:
your stdout
buffer is never flushed since you forgot a \n
(you might add a fflush(NULL);
...) in the printf
inside my_handler
in your code
probably, the SIGFPE handler restarts again the machine code instruction triggering it. (More exactly, after returning from sigreturn(2) your machine is in the same state as it was before SIGFPE
was delivered, so the same divide-by-zero condition happens, etc...)
It is difficult (but painfully possible, if you accept coding hardware-specific and operating-system specific code) to handle SIGFPE
; you would use sigaction(2) with SA_SIGINFO
and handle the third argument to the signal handler (which is a ucontext_t
pointer indirectly giving the machine state, including processor registers, which you might change inside your handler; in particular you could change your return program counter there). You might also consider using sigsetjmp(3) inside your signal handler (but it is in theory forbidden, since not async-signal-safe).
(You certainly need to understand the details of your processor's instruction set architecture and your operating system's ABI; and you probably would need a week of coding work after having mastered these)
In a portable POSIX way, SIGFPE
cannot really be handled, as explained in Blue Moon's answer
Probably, the runtime of JVM or of SBCL is handling SIGFPE
in a machine & operating system specific way to report zero-divides as divide-by-zero exceptions .... (to Java programs for JVM, to Common Lisp programs for SBCL). Alternatively their JIT or compiler machinery could generate a test before every division.
BTW, a flag set inside a signal handler should be declared volatile sig_atomic_t
. See POSIX specification about <signal.h>
As a pragmatical rule of thumb, a POSIX portable and robust signal handler should only set some volatile sig_atomic_t
and/or perhaps write(2) a few bytes to some pipe(7) (your process could set up a pipe to itself -as recommended by Qt-, with another thread and/or some event loop reading it), but this does not work for asynchronous process-generated signals like SIGFPE
, SIGBUS
, SIGILL
, and SIGSEGV
, etc... (which could only be handled by painful computer-specific code).
See also this answer to a very related question.
At last, on Linux, signal processing is believed to be not very quick. Even with a lot of machine-specific coding, emulating GNU Hurd external pagers by tricky SIGSEGV
handling (which would mmap
lazily ....) is believed to be quite slow.