cvs commit: src/sys/sys signalvar.h
Bruce Evans
bde at zeta.org.au
Mon Nov 10 00:27:51 PST 2003
On Sun, 9 Nov 2003, Kris Kennaway wrote:
> On Sun, Nov 09, 2003 at 07:11:08PM -0800, David Xu wrote:
> > davidxu 2003/11/09 19:11:08 PST
> >
> > FreeBSD src repository
> >
> > Modified files:
> > sys/sys signalvar.h
> > Log:
> > If a thread masks all its signal, in cursig(), no signal will be exchanged
> > with debugger, so testing P_TRACED in SIGPENDING is useless. This test also
> > is the culprit which causes lots of 'failed to set signal flags properly for
> > ast()' to be printed on console which is just a false complaint.
>
> Yay! This has been on my bug list for ages.
Me too. See the appended mail which diagnosed the problem with P_TRACED
and another with P_PPWAIT last March. Progress was stalled because no
one replied. I rarely see the dignostic since I normally have it turned
off (unconditionally compiled with more debugging info, but enabled by
a flag that is turned off).
Bruce
>From bde at zeta.org.au Thu Mar 13 03:25:44 2003 +1100
Date: Thu, 13 Mar 2003 03:25:41 +1100 (EST)
From: Bruce Evans <bde at zeta.org.au>
X-X-Sender: bde at gamplex.bde.org
To: Tim Robbins <tjr at FreeBSD.ORG>
cc: current at FreeBSD.ORG
Subject: Re: failed to set signal flags properly for ast()
In-Reply-To: <20030312141804.A12375 at dilbert.robbins.dropbear.id.au>
Message-ID: <20030313023818.O450 at gamplex.bde.org>
References: <20030312141804.A12375 at dilbert.robbins.dropbear.id.au>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Status: O
X-Status:
X-Keywords:
X-UID: 7515
On Wed, 12 Mar 2003, Tim Robbins wrote:
> Compile, run under gdb, then type "print test()" when the program receives
> SIGABRT. Seems to work incorrectly on 4.7 too.
>
> #include <stdio.h>
> #include <stdlib.h>
>
> void
> test(void)
> {
>
> puts("hello");
> }
>
> int
> main(int argc, char *argv[])
> {
>
> abort();
> exit(0);
> }
Thanks. At last it is possible to reproduce this bug :-).
The bug seems to be that issignal() is quite broken. It gets called
for masked signals in the P_TRACED case, but never does anything for
masked signals, but at least the following things poing to a need
for doing something for masked signals:
- the special case for P_TRACED in SIGPENDING()
- the incorrect behaviour of the above program in RELENG_4. I think
it misbehaves in the same way under -current except in the INVARIANTS
case the sanity check spews kernel printfs.
- code in NetBSD's issignal() to do something in the (p->p_stat == SSTOP)
case without even checking if there are any signals (masked or not).
This bug seems to go back to at least FreeBSD-1 (Net/2).
SIGPENDING() is also inconsistent with issignal() in the P_PPWAIT case.
I think this just wastes time doing null calls to issignal(), and
triggers the INVARIANTS check in the same way as the P_TRACED case
(see below). This seems to go back to FreeBSD-1 too.
SIGPENDING() is consistent with issignal() in the S_SIG case, but this
may be wrong since S_SIG is similar to P_TRACED.
The invariants check gets trigger as follows:
- sigpending() is called correctly.
- ast() clears the flags set by sigpending() and "handles" the signal
using "while ((sig == cursig(td)) != 0) postsig()". But cursig()
doesn't find any signals since all the pending ones are masked.
- userret() checks that pending signals were handled. It finds
unhandled masked ones and thinks they needed handling because
P_TRACED is set.
(IIRC, there is only a SIGTRAP pending to begin with, but attempting
to control the process using ^C^Z gave masked SIGINTs and SIGSTOPs
too).
Appart from the diagnostic, the incorrect working in -current is to
loop endlessly calling ast() and usrret(). ^C^Z doesn't stop it
because they are masked.
Bruce
>From bde at zeta.org.au Fri Mar 14 06:46:29 2003 +1100
Date: Fri, 14 Mar 2003 06:46:27 +1100 (EST)
From: Bruce Evans <bde at zeta.org.au>
X-X-Sender: bde at gamplex.bde.org
To: Tim Robbins <tjr at FreeBSD.ORG>
cc: current at FreeBSD.ORG
Subject: Re: failed to set signal flags properly for ast()
In-Reply-To: <20030312141804.A12375 at dilbert.robbins.dropbear.id.au>
Message-ID: <20030314061240.L817 at gamplex.bde.org>
References: <20030312141804.A12375 at dilbert.robbins.dropbear.id.au>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Status: O
X-Status:
X-Keywords:
X-UID: 7526
On Wed, 12 Mar 2003, Tim Robbins wrote:
> Compile, run under gdb, then type "print test()" when the program receives
> SIGABRT. Seems to work incorrectly on 4.7 too.
>
> #include <stdio.h>
> #include <stdlib.h>
>
> void
> test(void)
> {
>
> puts("hello");
> }
>
> int
> main(int argc, char *argv[])
> {
>
> abort();
> exit(0);
> }
Here's a simpler example:
%%%
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
sigset_t mask, omask;
volatile int i;
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, &omask);
exit(0);
}
%%%
Single stepping through this hangs at the end of the sigprocmask() and
triggers the INVARIANTS check. This is because masking SIGTRAP fouls
up trap handling. I first tried masking only SIGTRAP. This caused a
SIGSEGV on return of sigprocmask(). Masking SIGSEGV as well stops gdb
seeing any signals.
abort() causes similar misbehaviour by masking almost all signals.
gdb gets control for SIGABRT because SIGABRT is not masked, but
"call test()" hangs because it generates a SIGTRAP but SIGTRAP is
masked.
The system states are approx. 10% user and 90% sys for the hang in
both cases, so it seems that the misbehaviour is just the usual one
for bogusly masking signals for restartable exceptions if such an
exception occurs, and the bug is mainly in the sanity check
(SIGPENDING()'s P_TRACED check is less than a pessimization).
Bruce
More information about the cvs-src
mailing list