linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Signal left blocked after signal handler.
@ 2003-11-26 17:39 Bruce Perens
  2003-11-26 17:55 ` Linus Torvalds
  2003-11-27  9:20 ` Herbert Xu
  0 siblings, 2 replies; 10+ messages in thread
From: Bruce Perens @ 2003-11-26 17:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: torvalds

Hi,

A signal should be blocked while its signal handler is executing, and
then unblocked when the handler returns - unless SA_NOMASK is set.

-test9 and -test10 leave the signal _blocked_forever_.

This causes the build-time confidence test for Electric Fence to break,
and no doubt lots of other code.

If SA_NOMASK is set, the signal is not blocked.

Test program attached below.

	Thanks

	Bruce

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>

static sigjmp_buf	sjbuf;
static int		sig = SIGINT;

static void
handler(int i)
{
	struct sigaction	act;

	memset((void *)&act, 0, sizeof(act));
	act.sa_handler = SIG_DFL;

	fprintf(stderr, "Signal handler hit!\n");
	fflush(stderr);
	sigaction(sig, &act, 0);
	siglongjmp(sjbuf, 1);

}

static void
invoke_signal()
{
	struct sigaction	act;

	memset((void *)&act, 0, sizeof(act));
	act.sa_handler = handler;

	/* act.sa_flags = SA_NOMASK; */

	if ( sigsetjmp(sjbuf, 0) == 0 ) {
		sigaction(sig, &act, 0);
		fprintf(stderr, "Sending signal... ");
		fflush(stderr);
		kill(getpid(), sig);
		fprintf(stderr, "Huh? Nothing happened. Signal was left blocked.\n");
	}
}

int
main(int argc, char * * argv)
{
	sigset_t	set;

	sigemptyset(&set);
	sigaddset(&set, sig);

	invoke_signal();
	invoke_signal();
	fprintf(stderr, "Unblocking signal... ");
	if ( sigsetjmp(sjbuf, 0) == 0 ) {
		sigprocmask(SIG_UNBLOCK,  &set, 0);
	}

	return 0;
}

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Signal left blocked after signal handler.
  2003-11-26 17:39 Signal left blocked after signal handler Bruce Perens
@ 2003-11-26 17:55 ` Linus Torvalds
       [not found]   ` <3FC4ED5F.4090901@perens.com>
  2003-11-27  9:20 ` Herbert Xu
  1 sibling, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2003-11-26 17:55 UTC (permalink / raw)
  To: Bruce Perens, Ulrich Drepper; +Cc: Kernel Mailing List


[ Uli added to participants ]

On Wed, 26 Nov 2003, Bruce Perens wrote:
>
> A signal should be blocked while its signal handler is executing, and
> then unblocked when the handler returns - unless SA_NOMASK is set.
>
> -test9 and -test10 leave the signal _blocked_forever_.

>From what I can tell, this is a glibc bug. Do an "strace" on the program,
and see how "siglongjmp()" doesn't appear to do any system calls at all.

It's up to siglongjmp() to restore the signal mask that it saved on
sigsetjmp().

What library version are you using (but yes, I see the same thing with
"Fedora Core 1").

In fact, with strace I don't even see where the signal mask would be
_saved_ in sigsetjmp. So as far as I can tell, this just cannot work.

			Linus

--- rest of email saved for Uli ---
>
> This causes the build-time confidence test for Electric Fence to break,
> and no doubt lots of other code.
>
> If SA_NOMASK is set, the signal is not blocked.
>
> Test program attached below.
>
> 	Thanks
>
> 	Bruce
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <signal.h>
> #include <setjmp.h>
>
> static sigjmp_buf	sjbuf;
> static int		sig = SIGINT;
>
> static void
> handler(int i)
> {
> 	struct sigaction	act;
>
> 	memset((void *)&act, 0, sizeof(act));
> 	act.sa_handler = SIG_DFL;
>
> 	fprintf(stderr, "Signal handler hit!\n");
> 	fflush(stderr);
> 	sigaction(sig, &act, 0);
> 	siglongjmp(sjbuf, 1);
>
> }
>
> static void
> invoke_signal()
> {
> 	struct sigaction	act;
>
> 	memset((void *)&act, 0, sizeof(act));
> 	act.sa_handler = handler;
>
> 	/* act.sa_flags = SA_NOMASK; */
>
> 	if ( sigsetjmp(sjbuf, 0) == 0 ) {
> 		sigaction(sig, &act, 0);
> 		fprintf(stderr, "Sending signal... ");
> 		fflush(stderr);
> 		kill(getpid(), sig);
> 		fprintf(stderr, "Huh? Nothing happened. Signal was left blocked.\n");
> 	}
> }
>
> int
> main(int argc, char * * argv)
> {
> 	sigset_t	set;
>
> 	sigemptyset(&set);
> 	sigaddset(&set, sig);
>
> 	invoke_signal();
> 	invoke_signal();
> 	fprintf(stderr, "Unblocking signal... ");
> 	if ( sigsetjmp(sjbuf, 0) == 0 ) {
> 		sigprocmask(SIG_UNBLOCK,  &set, 0);
> 	}
>
> 	return 0;
> }
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Signal left blocked after signal handler.
       [not found]   ` <3FC4ED5F.4090901@perens.com>
@ 2003-11-26 18:21     ` Linus Torvalds
       [not found]     ` <3FC4EF24.9040307@perens.com>
  1 sibling, 0 replies; 10+ messages in thread
From: Linus Torvalds @ 2003-11-26 18:21 UTC (permalink / raw)
  To: Bruce Perens; +Cc: Ulrich Drepper, Kernel Mailing List


On Wed, 26 Nov 2003, Bruce Perens wrote:
>
> Sigsetjmp will save and restore the signal mask ONLY if its second
> argument is nonzero. The libc code is correct.

Oh, I didn't notice that part.

> The test program works properly under 2.4 .

What do you mean "properly"? If you're not saving/restoring the sigmasks,
then the 2.6.x behaviour is the right one and your program is buggy.

What's your point?

		Linus

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Signal left blocked after signal handler.
       [not found]     ` <3FC4EF24.9040307@perens.com>
@ 2003-11-26 18:34       ` Linus Torvalds
       [not found]       ` <3FC4F248.8060307@perens.com>
  1 sibling, 0 replies; 10+ messages in thread
From: Linus Torvalds @ 2003-11-26 18:34 UTC (permalink / raw)
  To: Bruce Perens; +Cc: Ulrich Drepper, Kernel Mailing List



On Wed, 26 Nov 2003, Bruce Perens wrote:
>
> OK, I see. The signal remains blocked forever if we jump out of the
> handler. This is not the case on 2.4 . So, is this is semantic change?

It _shouldn't_ be a semantic change. Quite frankly, 2.4.x shouldn't work
the way you describe either.

I wonder if it's the "sigaction()" call in the handler that unblocks the
signal in 2.4.x.

		Linus

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Never mind. Re: Signal left blocked after signal handler.
       [not found]       ` <3FC4F248.8060307@perens.com>
@ 2003-11-26 18:45         ` Linus Torvalds
  2003-11-26 19:04           ` Bruce Perens
  0 siblings, 1 reply; 10+ messages in thread
From: Linus Torvalds @ 2003-11-26 18:45 UTC (permalink / raw)
  To: Bruce Perens; +Cc: Ulrich Drepper, Kernel Mailing List



On Wed, 26 Nov 2003, Bruce Perens wrote:
>
> The test code works on 2.4, but the electric fence confidence test does
> not. Maybe something odd with SIGSEGV, which is
> what that confidence test is catching. I will go back and see why.

One difference in 2.4.x and 2.6.x is the signal blocking wrt blocked
signals that are _forced_ (ie anything that is thread-synchronous, like a
SIGSEGV/SIGTRAP/SIGBUS that happens as a result of a fault):

 - in 2.4.x they will just punch through the block
 - in 2.6.x they will refuse to punch through a blocked signal, but
   since they can't be delivered they will cause the process to be
   killed.

Trivial test program:

	#include <signal.h>
	#include <stdlib.h>

	void sigsegv(int sig)
	{
		*(int *)0=0;
	}

	int main(int argc, char **argv)
	{
		struct sigaction sa = { .sa_handler = sigsegv };

		sigaction(SIGSEGV, &sa, NULL);
		*(int *)0 = 0;
	}

and in 2.4.x this will cause infinte SIGSEGV's (well, they'll be caught by
the stack size eventually, but you see the problem: do a "strace" to see
what's going on). In 2.6.x the second SIGSEGV will just kill the program
immediately.

If you _want_ the recursive behaviour, you should add

	.sa_flags = SA_NODEFER

to the sigaction initializer.

I don't understand why your test-program works differently on 2.4.x,
though, since a "kill()" system call is _not_ thread-synchronous, and
should never punch through anything. Not even on 2.4.x.

		Linus

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Never mind. Re: Signal left blocked after signal handler.
  2003-11-26 18:45         ` Never mind. " Linus Torvalds
@ 2003-11-26 19:04           ` Bruce Perens
  2003-11-26 19:14             ` Linus Torvalds
  0 siblings, 1 reply; 10+ messages in thread
From: Bruce Perens @ 2003-11-26 19:04 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Ulrich Drepper, Kernel Mailing List

What happened is that I attempted to simplify the test code to send to 
you, and simplified out the problem by using
kill() instead of causing a fault. :-)

It's just what you describe here:

>One difference in 2.4.x and 2.6.x is the signal blocking wrt blocked
>signals that are _forced_ (ie anything that is thread-synchronous, like a
>SIGSEGV/SIGTRAP/SIGBUS that happens as a result of a fault):
>
> - in 2.4.x they will just punch through the block
> - in 2.6.x they will refuse to punch through a blocked signal, but
>   since they can't be delivered they will cause the process to be
>   killed
>  
>
The behavior of 2.4 seems to be the same used by some dozens of Unix 
systems upon which my confidence test passed.

I agree that we should not be wrong in the same way as everyone else, 
and wonder if POSIX says anything about this. I could have been the only 
one using this "feature".

    Thanks

    Bruce



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Never mind. Re: Signal left blocked after signal handler.
  2003-11-26 19:04           ` Bruce Perens
@ 2003-11-26 19:14             ` Linus Torvalds
  2003-11-26 19:34               ` Posix says "undefined". " Bruce Perens
  2003-11-26 19:52               ` Never mind. " Jamie Lokier
  0 siblings, 2 replies; 10+ messages in thread
From: Linus Torvalds @ 2003-11-26 19:14 UTC (permalink / raw)
  To: Bruce Perens; +Cc: Ulrich Drepper, Kernel Mailing List



On Wed, 26 Nov 2003, Bruce Perens wrote:
>
> The behavior of 2.4 seems to be the same used by some dozens of Unix
> systems upon which my confidence test passed.

Interesting. I know the 2.4.x behaviour wasn't arrived at due to any
"compatibility testing" - it was purely a matter of "minimal code". The
fact that other unixes did the same despite no other commonalities is
interesting in itself ;)

But we actually had another unrelated thread about this last week, where
SIGTRAP on x86 worked differently under Linux and FreeBSD (both 2.4.x and
2.6.x behaviour differed from BSD behaviour), so clearly it's _not_ a 100%
correlation.

> I agree that we should not be wrong in the same way as everyone else,
> and wonder if POSIX says anything about this. I could have been the only
> one using this "feature".

I can't say that I'd ever seen this documented anywhere.

I personally think it is "good taste" to actually set the SA_NODEFER flag
if you know you depend on the behaviour, but if there are lots of existing
applications that actually depend on the "forced punch-through" behaviour,
then I'll obviously have to change the 2.6.x behaviour (a stable
user-level ABI is a lot more important than my personal preferences).

But if ElectricFence is the only thing that cares, I'd rather just EF
added a SA_NODEFER..

		Linus

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Posix says "undefined". Re: Signal left blocked after signal handler.
  2003-11-26 19:14             ` Linus Torvalds
@ 2003-11-26 19:34               ` Bruce Perens
  2003-11-26 19:52               ` Never mind. " Jamie Lokier
  1 sibling, 0 replies; 10+ messages in thread
From: Bruce Perens @ 2003-11-26 19:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Ulrich Drepper, Kernel Mailing List

Linus,

Posix says the behavior is undefined. See 
http://www.opengroup.org/onlinepubs/007904975/functions/sigprocmask.html .
I think it makes sense to leave the 2.6 behavior as it is.

    Thanks

    Bruce

Linus Torvalds wrote:

> I personally think it is "good taste" to actually set the SA_NODEFER flag

> if you know you depend on the behaviour, but if there are lots of existing
>
>applications that actually depend on the "forced punch-through" behaviour,
>then I'll obviously have to change the 2.6.x behaviour (a stable
>user-level ABI is a lot more important than my personal preferences).
>
>But if ElectricFence is the only thing that cares, I'd rather just EF
>added a SA_NODEFER..
>  
>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Never mind. Re: Signal left blocked after signal handler.
  2003-11-26 19:14             ` Linus Torvalds
  2003-11-26 19:34               ` Posix says "undefined". " Bruce Perens
@ 2003-11-26 19:52               ` Jamie Lokier
  1 sibling, 0 replies; 10+ messages in thread
From: Jamie Lokier @ 2003-11-26 19:52 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Bruce Perens, Ulrich Drepper, Kernel Mailing List

Linus Torvalds wrote:
> I personally think it is "good taste" to actually set the SA_NODEFER flag
> if you know you depend on the behaviour, but if there are lots of existing
> applications that actually depend on the "forced punch-through" behaviour,
> then I'll obviously have to change the 2.6.x behaviour (a stable
> user-level ABI is a lot more important than my personal preferences).

I also have a program which depends on the behaviour of nesting
SIGSEGVs, however luckily I already set the SA_NODEFER flag :)

-- Jamie

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Signal left blocked after signal handler.
  2003-11-26 17:39 Signal left blocked after signal handler Bruce Perens
  2003-11-26 17:55 ` Linus Torvalds
@ 2003-11-27  9:20 ` Herbert Xu
  1 sibling, 0 replies; 10+ messages in thread
From: Herbert Xu @ 2003-11-27  9:20 UTC (permalink / raw)
  To: Bruce Perens, linux-kernel

Bruce Perens <bruce@perens.com> wrote:
> 
> Test program attached below.

I don't know about your other problems, but your code is buggy.

>        if ( sigsetjmp(sjbuf, 0) == 0 ) {

For sigsetjmp to be useful, you need to call it with a nonzero
value in the second argument.
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2003-11-27  9:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-26 17:39 Signal left blocked after signal handler Bruce Perens
2003-11-26 17:55 ` Linus Torvalds
     [not found]   ` <3FC4ED5F.4090901@perens.com>
2003-11-26 18:21     ` Linus Torvalds
     [not found]     ` <3FC4EF24.9040307@perens.com>
2003-11-26 18:34       ` Linus Torvalds
     [not found]       ` <3FC4F248.8060307@perens.com>
2003-11-26 18:45         ` Never mind. " Linus Torvalds
2003-11-26 19:04           ` Bruce Perens
2003-11-26 19:14             ` Linus Torvalds
2003-11-26 19:34               ` Posix says "undefined". " Bruce Perens
2003-11-26 19:52               ` Never mind. " Jamie Lokier
2003-11-27  9:20 ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).