diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-26 13:45:57 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-26 13:45:57 +0000 |
commit | 4e19a9c81a6e0b0608fcae1f1a5adbaa1893a17d (patch) | |
tree | 2121472f1df9153eec42f8da7e0517af443fdded | |
parent | 2b2e267b434d197fdbce2b36181dfd422da7f9d2 (diff) | |
download | busybox-w32-4e19a9c81a6e0b0608fcae1f1a5adbaa1893a17d.tar.gz busybox-w32-4e19a9c81a6e0b0608fcae1f1a5adbaa1893a17d.tar.bz2 busybox-w32-4e19a9c81a6e0b0608fcae1f1a5adbaa1893a17d.zip |
ash: hopefully close bug 4324. With testcase.
function old new delta
evaltree 621 869 +248
popstring 134 140 +6
-rw-r--r-- | shell/ash.c | 53 | ||||
-rw-r--r-- | shell/ash_test/ash-signals/signal2.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-signals/signal2.tests | 18 |
3 files changed, 57 insertions, 17 deletions
diff --git a/shell/ash.c b/shell/ash.c index 11174683e..5348e9572 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -203,7 +203,7 @@ struct globals_misc { | |||
203 | #define S_RESET 5 /* temporary - to reset a hard ignored sig */ | 203 | #define S_RESET 5 /* temporary - to reset a hard ignored sig */ |
204 | 204 | ||
205 | /* indicates specified signal received */ | 205 | /* indicates specified signal received */ |
206 | char gotsig[NSIG - 1]; | 206 | char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ |
207 | char *trap[NSIG]; | 207 | char *trap[NSIG]; |
208 | 208 | ||
209 | /* Rarely referenced stuff */ | 209 | /* Rarely referenced stuff */ |
@@ -7846,12 +7846,12 @@ dotrap(void) | |||
7846 | pendingsig = 0; | 7846 | pendingsig = 0; |
7847 | xbarrier(); | 7847 | xbarrier(); |
7848 | 7848 | ||
7849 | for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) { | 7849 | for (i = 1, q = gotsig; i < NSIG; i++, q++) { |
7850 | if (!*q) | 7850 | if (!*q) |
7851 | continue; | 7851 | continue; |
7852 | *q = '\0'; | 7852 | *q = '\0'; |
7853 | 7853 | ||
7854 | p = trap[i + 1]; | 7854 | p = trap[i]; |
7855 | if (!p) | 7855 | if (!p) |
7856 | continue; | 7856 | continue; |
7857 | skip = evalstring(p, SKIPEVAL); | 7857 | skip = evalstring(p, SKIPEVAL); |
@@ -7881,16 +7881,33 @@ static void prehash(union node *); | |||
7881 | static void | 7881 | static void |
7882 | evaltree(union node *n, int flags) | 7882 | evaltree(union node *n, int flags) |
7883 | { | 7883 | { |
7884 | |||
7885 | struct jmploc *volatile savehandler = exception_handler; | ||
7886 | struct jmploc jmploc; | ||
7884 | int checkexit = 0; | 7887 | int checkexit = 0; |
7885 | void (*evalfn)(union node *, int); | 7888 | void (*evalfn)(union node *, int); |
7886 | unsigned isor; | ||
7887 | int status; | 7889 | int status; |
7890 | |||
7888 | if (n == NULL) { | 7891 | if (n == NULL) { |
7889 | TRACE(("evaltree(NULL) called\n")); | 7892 | TRACE(("evaltree(NULL) called\n")); |
7890 | goto out; | 7893 | goto out1; |
7891 | } | 7894 | } |
7892 | TRACE(("pid %d, evaltree(%p: %d, %d) called\n", | 7895 | TRACE(("pid %d, evaltree(%p: %d, %d) called\n", |
7893 | getpid(), n, n->type, flags)); | 7896 | getpid(), n, n->type, flags)); |
7897 | |||
7898 | exception_handler = &jmploc; | ||
7899 | { | ||
7900 | int err = setjmp(jmploc.loc); | ||
7901 | if (err) { | ||
7902 | /* if it was a signal, check for trap handlers */ | ||
7903 | if (exception == EXSIG) | ||
7904 | goto out; | ||
7905 | /* continue on the way out */ | ||
7906 | exception_handler = savehandler; | ||
7907 | longjmp(exception_handler->loc, err); | ||
7908 | } | ||
7909 | } | ||
7910 | |||
7894 | switch (n->type) { | 7911 | switch (n->type) { |
7895 | default: | 7912 | default: |
7896 | #if DEBUG | 7913 | #if DEBUG |
@@ -7936,19 +7953,20 @@ evaltree(union node *n, int flags) | |||
7936 | goto calleval; | 7953 | goto calleval; |
7937 | case NAND: | 7954 | case NAND: |
7938 | case NOR: | 7955 | case NOR: |
7939 | case NSEMI: | 7956 | case NSEMI: { |
7957 | |||
7940 | #if NAND + 1 != NOR | 7958 | #if NAND + 1 != NOR |
7941 | #error NAND + 1 != NOR | 7959 | #error NAND + 1 != NOR |
7942 | #endif | 7960 | #endif |
7943 | #if NOR + 1 != NSEMI | 7961 | #if NOR + 1 != NSEMI |
7944 | #error NOR + 1 != NSEMI | 7962 | #error NOR + 1 != NSEMI |
7945 | #endif | 7963 | #endif |
7946 | isor = n->type - NAND; | 7964 | unsigned is_or = is_or = n->type - NAND; |
7947 | evaltree( | 7965 | evaltree( |
7948 | n->nbinary.ch1, | 7966 | n->nbinary.ch1, |
7949 | (flags | ((isor >> 1) - 1)) & EV_TESTED | 7967 | (flags | ((is_or >> 1) - 1)) & EV_TESTED |
7950 | ); | 7968 | ); |
7951 | if (!exitstatus == isor) | 7969 | if (!exitstatus == is_or) |
7952 | break; | 7970 | break; |
7953 | if (!evalskip) { | 7971 | if (!evalskip) { |
7954 | n = n->nbinary.ch2; | 7972 | n = n->nbinary.ch2; |
@@ -7959,6 +7977,7 @@ evaltree(union node *n, int flags) | |||
7959 | break; | 7977 | break; |
7960 | } | 7978 | } |
7961 | break; | 7979 | break; |
7980 | } | ||
7962 | case NIF: | 7981 | case NIF: |
7963 | evaltree(n->nif.test, EV_TESTED); | 7982 | evaltree(n->nif.test, EV_TESTED); |
7964 | if (evalskip) | 7983 | if (evalskip) |
@@ -7979,8 +7998,11 @@ evaltree(union node *n, int flags) | |||
7979 | exitstatus = status; | 7998 | exitstatus = status; |
7980 | break; | 7999 | break; |
7981 | } | 8000 | } |
8001 | |||
7982 | out: | 8002 | out: |
7983 | if ((checkexit & exitstatus)) | 8003 | exception_handler = savehandler; |
8004 | out1: | ||
8005 | if (checkexit & exitstatus) | ||
7984 | evalskip |= SKIPEVAL; | 8006 | evalskip |= SKIPEVAL; |
7985 | else if (pendingsig && dotrap()) | 8007 | else if (pendingsig && dotrap()) |
7986 | goto exexit; | 8008 | goto exexit; |
@@ -11907,18 +11929,15 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
11907 | if (!*ap) { | 11929 | if (!*ap) { |
11908 | for (signo = 0; signo < NSIG; signo++) { | 11930 | for (signo = 0; signo < NSIG; signo++) { |
11909 | if (trap[signo] != NULL) { | 11931 | if (trap[signo] != NULL) { |
11910 | const char *sn; | ||
11911 | |||
11912 | sn = get_signame(signo); | ||
11913 | out1fmt("trap -- %s %s\n", | 11932 | out1fmt("trap -- %s %s\n", |
11914 | single_quote(trap[signo]), sn); | 11933 | single_quote(trap[signo]), |
11934 | get_signame(signo)); | ||
11915 | } | 11935 | } |
11916 | } | 11936 | } |
11917 | return 0; | 11937 | return 0; |
11918 | } | 11938 | } |
11919 | if (!ap[1]) | 11939 | action = NULL; |
11920 | action = NULL; | 11940 | if (ap[1]) |
11921 | else | ||
11922 | action = *ap++; | 11941 | action = *ap++; |
11923 | while (*ap) { | 11942 | while (*ap) { |
11924 | signo = get_signum(*ap); | 11943 | signo = get_signum(*ap); |
diff --git a/shell/ash_test/ash-signals/signal2.right b/shell/ash_test/ash-signals/signal2.right new file mode 100644 index 000000000..96d2d6ad3 --- /dev/null +++ b/shell/ash_test/ash-signals/signal2.right | |||
@@ -0,0 +1,3 @@ | |||
1 | sleeping | ||
2 | child exits as expected | ||
3 | parent exits | ||
diff --git a/shell/ash_test/ash-signals/signal2.tests b/shell/ash_test/ash-signals/signal2.tests new file mode 100755 index 000000000..04f981c2d --- /dev/null +++ b/shell/ash_test/ash-signals/signal2.tests | |||
@@ -0,0 +1,18 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | $THIS_SH -c ' | ||
4 | cleanup() { | ||
5 | echo "child exits as expected" | ||
6 | exit | ||
7 | } | ||
8 | trap cleanup HUP | ||
9 | echo "sleeping" | ||
10 | sleep 1 | ||
11 | echo "BAD exit from child!" | ||
12 | ' & | ||
13 | |||
14 | child=$! | ||
15 | sleep 0.1 # let child install handler first | ||
16 | kill -HUP $child | ||
17 | wait | ||
18 | echo "parent exits" | ||