aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-26 13:45:57 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-26 13:45:57 +0000
commit4e19a9c81a6e0b0608fcae1f1a5adbaa1893a17d (patch)
tree2121472f1df9153eec42f8da7e0517af443fdded
parent2b2e267b434d197fdbce2b36181dfd422da7f9d2 (diff)
downloadbusybox-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.c53
-rw-r--r--shell/ash_test/ash-signals/signal2.right3
-rwxr-xr-xshell/ash_test/ash-signals/signal2.tests18
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 *);
7881static void 7881static void
7882evaltree(union node *n, int flags) 7882evaltree(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 @@
1sleeping
2child exits as expected
3parent 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 '
4cleanup() {
5 echo "child exits as expected"
6 exit
7}
8trap cleanup HUP
9echo "sleeping"
10sleep 1
11echo "BAD exit from child!"
12' &
13
14child=$!
15sleep 0.1 # let child install handler first
16kill -HUP $child
17wait
18echo "parent exits"