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.
|
/* Called to execute a trap.
|
||||||
* Single callsite - at the end of evaltree().
|
* 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
|
* Perhaps we should avoid entering new trap handlers
|
||||||
* while we are executing a trap handler. [is it a TODO?]
|
* while we are executing a trap handler. [is it a TODO?]
|
||||||
@ -8404,11 +8404,15 @@ evaltree(union node *n, int flags)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
exception_handler = savehandler;
|
exception_handler = savehandler;
|
||||||
|
|
||||||
out1:
|
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)
|
if (checkexit & exitstatus)
|
||||||
evalskip |= SKIPEVAL;
|
evalskip |= SKIPEVAL;
|
||||||
else if (pending_sig && dotrap())
|
|
||||||
goto exexit;
|
|
||||||
|
|
||||||
if (flags & EV_EXIT) {
|
if (flags & EV_EXIT) {
|
||||||
exexit:
|
exexit:
|
||||||
@ -8740,7 +8744,7 @@ poplocalvars(void)
|
|||||||
while ((lvp = localvars) != NULL) {
|
while ((lvp = localvars) != NULL) {
|
||||||
localvars = lvp->next;
|
localvars = lvp->next;
|
||||||
vp = lvp->vp;
|
vp = lvp->vp;
|
||||||
TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
|
TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
|
||||||
if (vp == NULL) { /* $- saved */
|
if (vp == NULL) { /* $- saved */
|
||||||
memcpy(optlist, lvp->text, sizeof(optlist));
|
memcpy(optlist, lvp->text, sizeof(optlist));
|
||||||
free((char*)lvp->text);
|
free((char*)lvp->text);
|
||||||
@ -13009,10 +13013,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (e == EXERROR)
|
if (e == EXERROR)
|
||||||
exitstatus = 2;
|
exitstatus = 2;
|
||||||
s = state;
|
s = state;
|
||||||
if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
|
if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
|
||||||
exitshell();
|
exitshell();
|
||||||
if (e == EXINT)
|
}
|
||||||
|
if (e == EXINT) {
|
||||||
outcslow('\n', stderr);
|
outcslow('\n', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
popstackmark(&smark);
|
popstackmark(&smark);
|
||||||
FORCE_INT_ON; /* enable interrupts */
|
FORCE_INT_ON; /* enable interrupts */
|
||||||
@ -13105,6 +13111,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
_mcleanup();
|
_mcleanup();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
TRACE(("End of main reached\n"));
|
||||||
exitshell();
|
exitshell();
|
||||||
/* NOTREACHED */
|
/* 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…
x
Reference in New Issue
Block a user