ash: fix signal and "set -e" interaction
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
5b3151c201
commit
b563f62bbb
19
shell/ash.c
19
shell/ash.c
@ -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 */
|
||||
}
|
||||
|
3
shell/ash_test/ash-signals/signal8.right
Normal file
3
shell/ash_test/ash-signals/signal8.right
Normal file
@ -0,0 +1,3 @@
|
||||
Removing traps
|
||||
End of exit_func
|
||||
Done: 0
|
18
shell/ash_test/ash-signals/signal8.tests
Executable file
18
shell/ash_test/ash-signals/signal8.tests
Executable 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: $?
|
3
shell/ash_test/ash-signals/signal9.right
Normal file
3
shell/ash_test/ash-signals/signal9.right
Normal file
@ -0,0 +1,3 @@
|
||||
Removing traps
|
||||
End of exit_func
|
||||
Done: 0
|
21
shell/ash_test/ash-signals/signal9.tests
Executable file
21
shell/ash_test/ash-signals/signal9.tests
Executable 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: $?
|
Loading…
Reference in New Issue
Block a user