aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-09-25 17:15:13 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-09-25 17:15:13 +0200
commitb563f62bbb1c9a6d931924f8fd7c3e52bb3d5875 (patch)
tree617e5a8de03257f9695fd10a496601c607f6803d
parent5b3151c201f4a67e998ec054d653e8177679d505 (diff)
downloadbusybox-w32-b563f62bbb1c9a6d931924f8fd7c3e52bb3d5875.tar.gz
busybox-w32-b563f62bbb1c9a6d931924f8fd7c3e52bb3d5875.tar.bz2
busybox-w32-b563f62bbb1c9a6d931924f8fd7c3e52bb3d5875.zip
ash: fix signal and "set -e" interaction
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c19
-rw-r--r--shell/ash_test/ash-signals/signal8.right3
-rwxr-xr-xshell/ash_test/ash-signals/signal8.tests18
-rw-r--r--shell/ash_test/ash-signals/signal9.right3
-rwxr-xr-xshell/ash_test/ash-signals/signal9.tests21
5 files changed, 58 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 9089adc63..ea835527e 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -8214,7 +8214,7 @@ static int evalstring(char *s, int mask);
8214 8214
8215/* Called to execute a trap. 8215/* Called to execute a trap.
8216 * Single callsite - at the end of evaltree(). 8216 * Single callsite - at the end of evaltree().
8217 * If we return non-zero, exaltree raises EXEXIT exception. 8217 * If we return non-zero, evaltree raises EXEXIT exception.
8218 * 8218 *
8219 * Perhaps we should avoid entering new trap handlers 8219 * Perhaps we should avoid entering new trap handlers
8220 * while we are executing a trap handler. [is it a TODO?] 8220 * while we are executing a trap handler. [is it a TODO?]
@@ -8404,11 +8404,15 @@ evaltree(union node *n, int flags)
8404 8404
8405 out: 8405 out:
8406 exception_handler = savehandler; 8406 exception_handler = savehandler;
8407
8407 out1: 8408 out1:
8409 /* Order of checks below is important:
8410 * signal handlers trigger before exit caused by "set -e".
8411 */
8412 if (pending_sig && dotrap())
8413 goto exexit;
8408 if (checkexit & exitstatus) 8414 if (checkexit & exitstatus)
8409 evalskip |= SKIPEVAL; 8415 evalskip |= SKIPEVAL;
8410 else if (pending_sig && dotrap())
8411 goto exexit;
8412 8416
8413 if (flags & EV_EXIT) { 8417 if (flags & EV_EXIT) {
8414 exexit: 8418 exexit:
@@ -8740,7 +8744,7 @@ poplocalvars(void)
8740 while ((lvp = localvars) != NULL) { 8744 while ((lvp = localvars) != NULL) {
8741 localvars = lvp->next; 8745 localvars = lvp->next;
8742 vp = lvp->vp; 8746 vp = lvp->vp;
8743 TRACE(("poplocalvar %s\n", vp ? vp->text : "-")); 8747 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
8744 if (vp == NULL) { /* $- saved */ 8748 if (vp == NULL) { /* $- saved */
8745 memcpy(optlist, lvp->text, sizeof(optlist)); 8749 memcpy(optlist, lvp->text, sizeof(optlist));
8746 free((char*)lvp->text); 8750 free((char*)lvp->text);
@@ -13009,10 +13013,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13009 if (e == EXERROR) 13013 if (e == EXERROR)
13010 exitstatus = 2; 13014 exitstatus = 2;
13011 s = state; 13015 s = state;
13012 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) 13016 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13013 exitshell(); 13017 exitshell();
13014 if (e == EXINT) 13018 }
13019 if (e == EXINT) {
13015 outcslow('\n', stderr); 13020 outcslow('\n', stderr);
13021 }
13016 13022
13017 popstackmark(&smark); 13023 popstackmark(&smark);
13018 FORCE_INT_ON; /* enable interrupts */ 13024 FORCE_INT_ON; /* enable interrupts */
@@ -13105,6 +13111,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13105 _mcleanup(); 13111 _mcleanup();
13106 } 13112 }
13107#endif 13113#endif
13114 TRACE(("End of main reached\n"));
13108 exitshell(); 13115 exitshell();
13109 /* NOTREACHED */ 13116 /* NOTREACHED */
13110} 13117}
diff --git a/shell/ash_test/ash-signals/signal8.right b/shell/ash_test/ash-signals/signal8.right
new file mode 100644
index 000000000..39572f30e
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal8.right
@@ -0,0 +1,3 @@
1Removing traps
2End of exit_func
3Done: 0
diff --git a/shell/ash_test/ash-signals/signal8.tests b/shell/ash_test/ash-signals/signal8.tests
new file mode 100755
index 000000000..731af7477
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal8.tests
@@ -0,0 +1,18 @@
1"$THIS_SH" -c '
2exit_func() {
3 echo "Removing traps"
4 trap - EXIT TERM INT
5 echo "End of exit_func"
6}
7set -e
8trap exit_func EXIT TERM INT
9sleep 2
10exit 77
11' &
12
13sleep 1
14# BUG: ash kills -PGRP, but in non-interactive shell we do not create pgrps!
15# In this case, bash kills by PID, not PGRP.
16kill -TERM %1
17wait
18echo Done: $?
diff --git a/shell/ash_test/ash-signals/signal9.right b/shell/ash_test/ash-signals/signal9.right
new file mode 100644
index 000000000..39572f30e
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal9.right
@@ -0,0 +1,3 @@
1Removing traps
2End of exit_func
3Done: 0
diff --git a/shell/ash_test/ash-signals/signal9.tests b/shell/ash_test/ash-signals/signal9.tests
new file mode 100755
index 000000000..18e71012b
--- /dev/null
+++ b/shell/ash_test/ash-signals/signal9.tests
@@ -0,0 +1,21 @@
1# Note: the inner script is a test which checks for a different bug
2# (ordering between INT handler and exit on "set -e"),
3# but so far I did not figure out how to simulate it non-interactively.
4
5"$THIS_SH" -c '
6exit_func() {
7 echo "Removing traps"
8 trap - EXIT TERM INT
9 echo "End of exit_func"
10}
11set -e
12trap exit_func EXIT TERM INT
13sleep 2
14exit 77
15' &
16
17child=$!
18sleep 1
19kill -TERM $child
20wait
21echo Done: $?