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>