ash: fix signal and "set -e" interaction

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-09-25 17:15:13 +02:00
parent 5b3151c201
commit b563f62bbb
5 changed files with 58 additions and 6 deletions

View File

@ -8214,7 +8214,7 @@ static int evalstring(char *s, int mask);
/* Called to execute a trap.
* Single callsite - at the end of evaltree().
* If we return non-zero, exaltree raises EXEXIT exception.
* If we return non-zero, evaltree raises EXEXIT exception.
*
* Perhaps we should avoid entering new trap handlers
* while we are executing a trap handler. [is it a TODO?]
@ -8404,11 +8404,15 @@ evaltree(union node *n, int flags)
out:
exception_handler = savehandler;
out1:
/* Order of checks below is important:
* signal handlers trigger before exit caused by "set -e".
*/
if (pending_sig && dotrap())
goto exexit;
if (checkexit & exitstatus)
evalskip |= SKIPEVAL;
else if (pending_sig && dotrap())
goto exexit;
if (flags & EV_EXIT) {
exexit:
@ -8740,7 +8744,7 @@ poplocalvars(void)
while ((lvp = localvars) != NULL) {
localvars = lvp->next;
vp = lvp->vp;
TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
if (vp == NULL) { /* $- saved */
memcpy(optlist, lvp->text, sizeof(optlist));
free((char*)lvp->text);
@ -13009,10 +13013,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
if (e == EXERROR)
exitstatus = 2;
s = state;
if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
exitshell();
if (e == EXINT)
}
if (e == EXINT) {
outcslow('\n', stderr);
}
popstackmark(&smark);
FORCE_INT_ON; /* enable interrupts */
@ -13105,6 +13111,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
_mcleanup();
}
#endif
TRACE(("End of main reached\n"));
exitshell();
/* NOTREACHED */
}

View File

@ -0,0 +1,3 @@
Removing traps
End of exit_func
Done: 0

View File

@ -0,0 +1,18 @@
"$THIS_SH" -c '
exit_func() {
echo "Removing traps"
trap - EXIT TERM INT
echo "End of exit_func"
}
set -e
trap exit_func EXIT TERM INT
sleep 2
exit 77
' &
sleep 1
# BUG: ash kills -PGRP, but in non-interactive shell we do not create pgrps!
# In this case, bash kills by PID, not PGRP.
kill -TERM %1
wait
echo Done: $?

View File

@ -0,0 +1,3 @@
Removing traps
End of exit_func
Done: 0

View File

@ -0,0 +1,21 @@
# Note: the inner script is a test which checks for a different bug
# (ordering between INT handler and exit on "set -e"),
# but so far I did not figure out how to simulate it non-interactively.
"$THIS_SH" -c '
exit_func() {
echo "Removing traps"
trap - EXIT TERM INT
echo "End of exit_func"
}
set -e
trap exit_func EXIT TERM INT
sleep 2
exit 77
' &
child=$!
sleep 1
kill -TERM $child
wait
echo Done: $?