Re: Catching SIGSEGV with signal() in 2.6

From: Ulrich Drepper
Date: Mon Apr 05 2004 - 23:13:43 EST


Kevin B. Hendricks wrote:

> So the code has been wrong since the beginning and we were just "lucky" it
> worked in all pre-2.6 kernels?

The old code depended on undefined behavior.


> 1. before the next use of the handler we use signal again to properly set the
> signal handler (and the set of masked signals).

Where do you set the signal mask? That's the point. You don't. This
means jumping from the signal handler causes the signal to remain
blocked. And then


~~~~
If any of the SIGFPE, SIGILL, SIGSEGV, or SIGBUS signals are generated
while they are blocked, the result is undefined, unless the signal was
generated by the kill() function, the sigqueue() function, or the
raise() function.
~~~~

(see pthread_sigmask in POSIX) comes into play.

The second SIGSEGV signal is created with the signal blocked and since
it's neither of the functions mentioned in the text below which creates
the signal anything can happen. The old kernel queued the signal, the
new kernel terminates the process which is much better IMO. Try the
attached program to see why. Also note, the 2.4 behavior is
inconsistent. If no handler is installed the process is terminated,
regardless of the signal being masked.

--
â Ulrich Drepper â Red Hat, Inc. â 444 Castro St â Mountain View, CA â
#include <signal.h>
int *p;
void
sh (int sig)
{
}
int
main(void)
{
sigset_t s;
sigemptyset (&s);
sigaddset (&s, SIGSEGV);
sigprocmask (SIG_BLOCK, &s, 0);
signal(SIGSEGV, sh);
return *p;
}