sh: If a SIGINT or SIGQUIT interrupts "wait", return status 128+sig.

This commit is contained in:
Jilles Tjoelker 2013-02-23 22:50:57 +00:00
parent b2a67e7b16
commit 25e0f0f577
7 changed files with 47 additions and 20 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -33,7 +33,7 @@
* $FreeBSD$
*/
extern int pendingsigs;
extern volatile sig_atomic_t pendingsig;
extern int in_dotrap;
extern volatile sig_atomic_t gotwinch;

View File

@ -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
r=$?
[ "$r" -gt 128 ] && [ -n "$trapped" ]

View File

@ -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
r=$?
[ "$r" -gt 128 ] && [ -n "$trapped" ]