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 /shell | |
| 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
Diffstat (limited to 'shell')
| -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" | ||
