diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-09-25 17:15:13 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-09-25 17:15:13 +0200 |
commit | b563f62bbb1c9a6d931924f8fd7c3e52bb3d5875 (patch) | |
tree | 617e5a8de03257f9695fd10a496601c607f6803d | |
parent | 5b3151c201f4a67e998ec054d653e8177679d505 (diff) | |
download | busybox-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.c | 19 | ||||
-rw-r--r-- | shell/ash_test/ash-signals/signal8.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-signals/signal8.tests | 18 | ||||
-rw-r--r-- | shell/ash_test/ash-signals/signal9.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-signals/signal9.tests | 21 |
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 @@ | |||
1 | Removing traps | ||
2 | End of exit_func | ||
3 | Done: 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 ' | ||
2 | exit_func() { | ||
3 | echo "Removing traps" | ||
4 | trap - EXIT TERM INT | ||
5 | echo "End of exit_func" | ||
6 | } | ||
7 | set -e | ||
8 | trap exit_func EXIT TERM INT | ||
9 | sleep 2 | ||
10 | exit 77 | ||
11 | ' & | ||
12 | |||
13 | sleep 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. | ||
16 | kill -TERM %1 | ||
17 | wait | ||
18 | echo 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 @@ | |||
1 | Removing traps | ||
2 | End of exit_func | ||
3 | Done: 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 ' | ||
6 | exit_func() { | ||
7 | echo "Removing traps" | ||
8 | trap - EXIT TERM INT | ||
9 | echo "End of exit_func" | ||
10 | } | ||
11 | set -e | ||
12 | trap exit_func EXIT TERM INT | ||
13 | sleep 2 | ||
14 | exit 77 | ||
15 | ' & | ||
16 | |||
17 | child=$! | ||
18 | sleep 1 | ||
19 | kill -TERM $child | ||
20 | wait | ||
21 | echo Done: $? | ||