From 25e0f0f577987046d53a63ab7122775bbc344285 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 23 Feb 2013 22:50:57 +0000 Subject: [PATCH] sh: If a SIGINT or SIGQUIT interrupts "wait", return status 128+sig. --- bin/sh/eval.c | 2 +- bin/sh/jobs.c | 2 +- bin/sh/main.c | 2 +- bin/sh/trap.c | 35 +++++++++++++----------- bin/sh/trap.h | 2 +- tools/regression/bin/sh/builtins/wait4.0 | 12 ++++++++ tools/regression/bin/sh/builtins/wait5.0 | 12 ++++++++ 7 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 tools/regression/bin/sh/builtins/wait4.0 create mode 100644 tools/regression/bin/sh/builtins/wait5.0 diff --git a/bin/sh/eval.c b/bin/sh/eval.c index b40fffde85ad..0972b105a2ed 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -301,7 +301,7 @@ evaltree(union node *n, int flags) } while (n != NULL); out: popstackmark(&smark); - if (pendingsigs) + if (pendingsig) dotrap(); if (eflag && exitstatus != 0 && do_etest) exitshell(exitstatus); diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index c86394f0d46c..5a2790b4ade9 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -521,7 +521,7 @@ waitcmd(int argc, char **argv) } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1); in_waitcmd--; - return 0; + return pendingsig + 128; } diff --git a/bin/sh/main.c b/bin/sh/main.c index 66e133532957..5dc050ffb701 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -196,7 +196,7 @@ cmdloop(int top) TRACE(("cmdloop(%d) called\n", top)); setstackmark(&smark); for (;;) { - if (pendingsigs) + if (pendingsig) dotrap(); inter = 0; if (iflag && top) { diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 521c5110cb3c..0a9eb60f5fb8 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$"); MKINIT char sigmode[NSIG]; /* current value of signal */ -int pendingsigs; /* indicates some signal received */ +volatile sig_atomic_t pendingsig; /* indicates some signal received */ int in_dotrap; /* do we execute in a trap handler? */ static char *volatile trap[NSIG]; /* trap handler commands */ static volatile sig_atomic_t gotsig[NSIG]; @@ -388,22 +388,25 @@ onsig(int signo) return; } - if (signo != SIGCHLD || !ignore_sigchld) - gotsig[signo] = 1; - pendingsigs++; - /* If we are currently in a wait builtin, prepare to break it */ - if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) - breakwaitcmd = 1; - /* - * If a trap is set, not ignored and not the null command, we need - * to make sure traps are executed even when a child blocks signals. - */ - if (Tflag && - trap[signo] != NULL && - ! (trap[signo][0] == '\0') && - ! (trap[signo][0] == ':' && trap[signo][1] == '\0')) + if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) { breakwaitcmd = 1; + pendingsig = signo; + } + + if (trap[signo] != NULL && trap[signo][0] != '\0' && + (signo != SIGCHLD || !ignore_sigchld)) { + gotsig[signo] = 1; + pendingsig = signo; + + /* + * If a trap is set, not ignored and not the null command, we + * need to make sure traps are executed even when a child + * blocks signals. + */ + if (Tflag && !(trap[signo][0] == ':' && trap[signo][1] == '\0')) + breakwaitcmd = 1; + } #ifndef NO_HISTORY if (signo == SIGWINCH) @@ -424,7 +427,7 @@ dotrap(void) in_dotrap++; for (;;) { - pendingsigs = 0; + pendingsig = 0; for (i = 1; i < NSIG; i++) { if (gotsig[i]) { gotsig[i] = 0; diff --git a/bin/sh/trap.h b/bin/sh/trap.h index 61a17ec05174..0a05d8d0ad21 100644 --- a/bin/sh/trap.h +++ b/bin/sh/trap.h @@ -33,7 +33,7 @@ * $FreeBSD$ */ -extern int pendingsigs; +extern volatile sig_atomic_t pendingsig; extern int in_dotrap; extern volatile sig_atomic_t gotwinch; diff --git a/tools/regression/bin/sh/builtins/wait4.0 b/tools/regression/bin/sh/builtins/wait4.0 new file mode 100644 index 000000000000..79351315d384 --- /dev/null +++ b/tools/regression/bin/sh/builtins/wait4.0 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX` +trap 'rm -rf $T' 0 +cd $T || exit 3 +mkfifo fifo1 +trapped= +trap trapped=1 QUIT +{ kill -QUIT $$; sleep 1; exit 4; } >fifo1 & +wait $! fifo1 & +wait