Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 17 Oct 2013 10:31:58 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Julio Merino <julio@meroh.net>
Cc:        ppc@freebsd.org
Subject:   Re: powerpc/183040: Nested signal handling is broken
Message-ID:  <20131017073158.GB3865@kib.kiev.ua>
In-Reply-To: <201310162349.r9GNnDud012497@mastodon.meroh.net>
References:  <201310162349.r9GNnDud012497@mastodon.meroh.net>

next in thread | previous in thread | raw e-mail | index | archive | help

--/w6WUUxYkubDgwa5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Oct 16, 2013 at 07:49:13PM -0400, Julio Merino wrote:
>=20
> >Number:         183040
> >Category:       powerpc
> >Synopsis:       Nested signal handling is broken
> >Confidential:   no
> >Severity:       serious
> >Priority:       medium
> >Responsible:    freebsd-ppc
> >State:          open
> >Quarter:       =20
> >Keywords:      =20
> >Date-Required:
> >Class:          sw-bug
> >Submitter-Id:   current-users
> >Arrival-Date:   Thu Oct 17 00:00:00 UTC 2013
> >Closed-Date:
> >Last-Modified:
> >Originator:     Julio Merino
> >Release:        FreeBSD 11.0-CURRENT powerpc
> >Organization:
> >Environment:
> System: FreeBSD mastodon.meroh.net 11.0-CURRENT FreeBSD 11.0-CURRENT #9 r=
256450M: Mon Oct 14 16:35:08 EDT 2013 jmmv@mastodon.meroh.net:/usr/obj/usr/=
src/sys/GENERIC64 powerpc
>=20
> Also affects FreeBSD 10.0 alphas.
>=20
> =09
> >Description:
> 	When programming a given signal twice in a nested manner, the
> 	unprogramming of the top-most signal handler does not properly
> 	restore the previous (non-default handler).  In other words:
>=20
> 	program signal X
> 	  program signal X
> 	    deliver signal X to self -- custom handler runs
> 	  unprogram signal X
> 	  deliver signal X to self -- default handler runs or not delivered
> 	unprogram signal X
>=20
> 	Interestingly, things seem to work well for X =3D SIGTERM but not
> 	for X =3D SIGHUP nor X =3D SIGINT.  I have not tested other signals.
>=20
> 	I have encountered this bug while running the kyua test suite
> 	on a powerpc64 machine (specifics detailed above) and noticing
> 	a couple of tests fail, which work well in other operating
> 	systems and in amd64.  The test case below is derived form the
> 	code in kyua.
>=20
> 	Here is the output of the test program on an amd64 machine,
> 	which to my knowledge is working properly:
>=20
> SIGNAL 1
> Programming at level 1
> Programming at level 0
> Signal 1 caught correctly
> Unprogramming at level 0
> Signal 1 caught correctly
> Unprogramming at level 1
>=20
> SIGNAL 2
> Programming at level 1
> Programming at level 0
> Signal 2 caught correctly
> Unprogramming at level 0
> Signal 2 caught correctly
> Unprogramming at level 1
>=20
> SIGNAL 15
> Programming at level 1
> Programming at level 0
> Signal 15 caught correctly
> Unprogramming at level 0
> Signal 15 caught correctly
> Unprogramming at level 1
>=20
> 	The same test program yields this on powerpc64:
>=20
> SIGNAL 1
> Programming at level 1
> Programming at level 0
> Signal 1 caught correctly
> Unprogramming at level 0
> a.out: Signal 1 not caught
>=20
> >How-To-Repeat:
> 	Build and run this test program:
>=20
> -----
> #include <err.h>
> #include <signal.h>
> #include <stdbool.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
>=20
> static bool caught =3D false;
>=20
> static void
> handler(const int signo)
> {
>     caught =3D true;
> }
>=20
> static void
> do_it(const int signo, const int level)
> {
>     struct sigaction sa, old_sa;
>=20
>     printf("Programming at level %d\n", level);
>=20
>     sa.sa_handler =3D handler;
>     sigemptyset(&sa.sa_mask);
>     sa.sa_flags =3D SA_RESTART;
>=20
>     if (sigaction(signo, &sa, &old_sa) =3D=3D -1)
>         err(EXIT_FAILURE, "sigaction program failed");
>=20
>     if (level > 0)
>         do_it(signo, level - 1);
>=20
>     caught =3D false;
>     kill(getpid(), signo);
>     if (caught)
>         printf("Signal %d caught correctly\n", signo);
>     else
>         errx(EXIT_FAILURE, "Signal %d not caught\n", signo);
>=20
>     if (sigaction(signo, &old_sa, NULL) =3D=3D -1)
>         err(EXIT_FAILURE, "sigaction unprogram failed");
>=20
>     printf("Unprogramming at level %d\n", level);
> }
>=20
> static void
> try_one_signal(const int signo, const int level)
> {
>     printf("SIGNAL %d\n", signo);
>     do_it(signo, level);
>     printf("\n");
> }
>=20
> int
> main(void)
> {
>     try_one_signal(SIGHUP, 1);
>     try_one_signal(SIGINT, 1);
>     try_one_signal(SIGTERM, 1);
>     return EXIT_SUCCESS;
> }

What you could do, is to localize the point where the breakage occur.
Add a function like this:

static void
print_sig_disposition(int signo)
{
	struct sigaction sa;
	sigaction(signo, NULL, &sa);
	printf("sig %d handler %p\n", signo, sa.sa_handler);
}

and sprinkle a calls to it often enough, to see where the reset of the
disposition happens.  Insert the call to the function into the signal
handler as well.

--/w6WUUxYkubDgwa5
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (FreeBSD)

iQIcBAEBAgAGBQJSX5JtAAoJEJDCuSvBvK1BaWoP/07mgLfpnYMMnQ0BbmjVwFYX
emwYOT3SCtHzr2wXqAVZTg598cj9y4raf7IZO+w71ywneJpeOG/Ymxw4eZE68sl5
lfV7oA/2jiPWQVxNCJ9XBscHr0m6e5Q+oQJqVL90zQfd/eJiyhrX8URuYbQsqZj2
BmSaF1z9PUXJJfXzlQsHe2zS0J+nHASt1YF81QAP/HWpzIhcQfs7dktzk2FqkBxR
Q+jGdhj36pcLXjU4dVcGQV2AWknvkQMHP3oZZXhm6KBjfcQ/pFwJnc9NSu4IATZ8
D+ogmKHinBsoP8ZAwf0NK1hoOn2HKzfnAOeWfelIcOISypPI3tRMQDEGh3yzoGRy
xFjV2y/NYSQ6gSDgAF7R+NSUcb1KEdTvmBaoeOFyxmLO27JkX/mlT7BJnZi7GDD0
tHn9CTi/G7mM0sXuCFD6Td+uJOG5nyrdq1eViiNjGVq4K4taqAfhwUlxG59uMILd
Q3YehhXQNUCSrRm+YP2id9AqRsTYaZGdnRXv94l5rI7+AhKmKe2TClVf5Lk23jPx
ShaIyBP6+S83onIrrqxICm4AYInN0KAmQuNt2QBphFNGuc52FK7LJEFJA6xQ0yQ7
/U4A2fnA1WHVmSu3xCJxOLrw9Pqby3uSNXhR7spITh9U4KNiFpLkKvF3DM8g0jhv
kiwpaKfg4jceS+yBPIsy
=NfKd
-----END PGP SIGNATURE-----

--/w6WUUxYkubDgwa5--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20131017073158.GB3865>