diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-19 21:59:35 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-19 21:59:35 +0000 |
commit | 653d8e79b21f39fa97c3043296e36971bb8ef555 (patch) | |
tree | 5324e83352c2db22b9835036be98afa3f1860069 | |
parent | 731de5ce76b42decdb8dce4277c839efde8b114f (diff) | |
download | busybox-w32-653d8e79b21f39fa97c3043296e36971bb8ef555.tar.gz busybox-w32-653d8e79b21f39fa97c3043296e36971bb8ef555.tar.bz2 busybox-w32-653d8e79b21f39fa97c3043296e36971bb8ef555.zip |
ash: make evaltree save/restore int suppression depth.
Hopefully this fixes bug 189. Not confirmed by users yet.
function old new delta
evaltree 809 842 +33
evalvar 1374 1376 +2
-rw-r--r-- | shell/ash.c | 116 |
1 files changed, 78 insertions, 38 deletions
diff --git a/shell/ash.c b/shell/ash.c index 9bb1d421e..a8383d805 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -30,7 +30,7 @@ | |||
30 | */ | 30 | */ |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * The follow should be set to reflect the type of system you have: | 33 | * The following should be set to reflect the type of system you have: |
34 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. | 34 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. |
35 | * define SYSV if you are running under System V. | 35 | * define SYSV if you are running under System V. |
36 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) | 36 | * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) |
@@ -40,6 +40,11 @@ | |||
40 | * a quit signal will generate a core dump. | 40 | * a quit signal will generate a core dump. |
41 | */ | 41 | */ |
42 | #define DEBUG 0 | 42 | #define DEBUG 0 |
43 | /* Tweak debug output verbosity here */ | ||
44 | #define DEBUG_TIME 0 | ||
45 | #define DEBUG_PID 1 | ||
46 | #define DEBUG_SIG 1 | ||
47 | |||
43 | #define PROFILE 0 | 48 | #define PROFILE 0 |
44 | 49 | ||
45 | #define IFS_BROKEN | 50 | #define IFS_BROKEN |
@@ -47,9 +52,9 @@ | |||
47 | #define JOBS ENABLE_ASH_JOB_CONTROL | 52 | #define JOBS ENABLE_ASH_JOB_CONTROL |
48 | 53 | ||
49 | #if DEBUG | 54 | #if DEBUG |
50 | #ifndef _GNU_SOURCE | 55 | # ifndef _GNU_SOURCE |
51 | #define _GNU_SOURCE | 56 | # define _GNU_SOURCE |
52 | #endif | 57 | # endif |
53 | #endif | 58 | #endif |
54 | 59 | ||
55 | #include "busybox.h" /* for applet_names */ | 60 | #include "busybox.h" /* for applet_names */ |
@@ -71,11 +76,11 @@ | |||
71 | #endif | 76 | #endif |
72 | 77 | ||
73 | #ifndef PIPE_BUF | 78 | #ifndef PIPE_BUF |
74 | #define PIPE_BUF 4096 /* amount of buffering in a pipe */ | 79 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ |
75 | #endif | 80 | #endif |
76 | 81 | ||
77 | #if defined(__uClinux__) | 82 | #if defined(__uClinux__) |
78 | #error "Do not even bother, ash will not run on NOMMU machine" | 83 | # error "Do not even bother, ash will not run on NOMMU machine" |
79 | #endif | 84 | #endif |
80 | 85 | ||
81 | 86 | ||
@@ -86,14 +91,6 @@ | |||
86 | #define CMDTABLESIZE 31 /* should be prime */ | 91 | #define CMDTABLESIZE 31 /* should be prime */ |
87 | 92 | ||
88 | 93 | ||
89 | /* ============ Misc helpers */ | ||
90 | |||
91 | #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) | ||
92 | |||
93 | /* C99 says: "char" declaration may be signed or unsigned by default */ | ||
94 | #define signed_char2int(sc) ((int)((signed char)sc)) | ||
95 | |||
96 | |||
97 | /* ============ Shell options */ | 94 | /* ============ Shell options */ |
98 | 95 | ||
99 | static const char *const optletters_optnames[] = { | 96 | static const char *const optletters_optnames[] = { |
@@ -257,7 +254,24 @@ extern struct globals_misc *const ash_ptr_to_globals_misc; | |||
257 | } while (0) | 254 | } while (0) |
258 | 255 | ||
259 | 256 | ||
257 | /* ============ DEBUG */ | ||
258 | #if DEBUG | ||
259 | static void trace_printf(const char *fmt, ...); | ||
260 | static void trace_vprintf(const char *fmt, va_list va); | ||
261 | # define TRACE(param) trace_printf param | ||
262 | # define TRACEV(param) trace_vprintf param | ||
263 | #else | ||
264 | # define TRACE(param) | ||
265 | # define TRACEV(param) | ||
266 | #endif | ||
267 | |||
268 | |||
260 | /* ============ Utility functions */ | 269 | /* ============ Utility functions */ |
270 | #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0) | ||
271 | |||
272 | /* C99 say: "char" declaration may be signed or unsigned by default */ | ||
273 | #define signed_char2int(sc) ((int)(signed char)(sc)) | ||
274 | |||
261 | static int isdigit_str9(const char *str) | 275 | static int isdigit_str9(const char *str) |
262 | { | 276 | { |
263 | int maxlen = 9 + 1; /* max 9 digits: 999999999 */ | 277 | int maxlen = 9 + 1; /* max 9 digits: 999999999 */ |
@@ -296,6 +310,12 @@ raise_exception(int e) | |||
296 | exception_type = e; | 310 | exception_type = e; |
297 | longjmp(exception_handler->loc, 1); | 311 | longjmp(exception_handler->loc, 1); |
298 | } | 312 | } |
313 | #if DEBUG | ||
314 | #define raise_exception(e) do { \ | ||
315 | TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \ | ||
316 | raise_exception(e); \ | ||
317 | } while (0) | ||
318 | #endif | ||
299 | 319 | ||
300 | /* | 320 | /* |
301 | * Called from trap.c when a SIGINT is received. (If the user specifies | 321 | * Called from trap.c when a SIGINT is received. (If the user specifies |
@@ -328,6 +348,12 @@ raise_interrupt(void) | |||
328 | raise_exception(ex_type); | 348 | raise_exception(ex_type); |
329 | /* NOTREACHED */ | 349 | /* NOTREACHED */ |
330 | } | 350 | } |
351 | #if DEBUG | ||
352 | #define raise_interrupt() do { \ | ||
353 | TRACE(("raising interrupt on line %d\n", __LINE__)); \ | ||
354 | raise_interrupt(); \ | ||
355 | } while (0) | ||
356 | #endif | ||
331 | 357 | ||
332 | #if ENABLE_ASH_OPTIMIZE_FOR_SIZE | 358 | #if ENABLE_ASH_OPTIMIZE_FOR_SIZE |
333 | static void | 359 | static void |
@@ -346,7 +372,9 @@ force_int_on(void) | |||
346 | raise_interrupt(); | 372 | raise_interrupt(); |
347 | } | 373 | } |
348 | #define FORCE_INT_ON force_int_on() | 374 | #define FORCE_INT_ON force_int_on() |
349 | #else | 375 | |
376 | #else /* !ASH_OPTIMIZE_FOR_SIZE */ | ||
377 | |||
350 | #define INT_ON do { \ | 378 | #define INT_ON do { \ |
351 | xbarrier(); \ | 379 | xbarrier(); \ |
352 | if (--suppressint == 0 && intpending) \ | 380 | if (--suppressint == 0 && intpending) \ |
@@ -358,7 +386,7 @@ force_int_on(void) | |||
358 | if (intpending) \ | 386 | if (intpending) \ |
359 | raise_interrupt(); \ | 387 | raise_interrupt(); \ |
360 | } while (0) | 388 | } while (0) |
361 | #endif /* ASH_OPTIMIZE_FOR_SIZE */ | 389 | #endif /* !ASH_OPTIMIZE_FOR_SIZE */ |
362 | 390 | ||
363 | #define SAVE_INT(v) ((v) = suppressint) | 391 | #define SAVE_INT(v) ((v) = suppressint) |
364 | 392 | ||
@@ -666,6 +694,12 @@ trace_printf(const char *fmt, ...) | |||
666 | 694 | ||
667 | if (debug != 1) | 695 | if (debug != 1) |
668 | return; | 696 | return; |
697 | if (DEBUG_TIME) | ||
698 | fprintf(tracefile, "%u ", (int) time(NULL)); | ||
699 | if (DEBUG_PID) | ||
700 | fprintf(tracefile, "[%u] ", (int) getpid()); | ||
701 | if (DEBUG_SIG) | ||
702 | fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); | ||
669 | va_start(va, fmt); | 703 | va_start(va, fmt); |
670 | vfprintf(tracefile, fmt, va); | 704 | vfprintf(tracefile, fmt, va); |
671 | va_end(va); | 705 | va_end(va); |
@@ -676,6 +710,12 @@ trace_vprintf(const char *fmt, va_list va) | |||
676 | { | 710 | { |
677 | if (debug != 1) | 711 | if (debug != 1) |
678 | return; | 712 | return; |
713 | if (DEBUG_TIME) | ||
714 | fprintf(tracefile, "%u ", (int) time(NULL)); | ||
715 | if (DEBUG_PID) | ||
716 | fprintf(tracefile, "[%u] ", (int) getpid()); | ||
717 | if (DEBUG_SIG) | ||
718 | fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint); | ||
679 | vfprintf(tracefile, fmt, va); | 719 | vfprintf(tracefile, fmt, va); |
680 | } | 720 | } |
681 | 721 | ||
@@ -980,14 +1020,6 @@ showtree(union node *n) | |||
980 | shtree(n, 1, NULL, stdout); | 1020 | shtree(n, 1, NULL, stdout); |
981 | } | 1021 | } |
982 | 1022 | ||
983 | #define TRACE(param) trace_printf param | ||
984 | #define TRACEV(param) trace_vprintf param | ||
985 | |||
986 | #else | ||
987 | |||
988 | #define TRACE(param) | ||
989 | #define TRACEV(param) | ||
990 | |||
991 | #endif /* DEBUG */ | 1023 | #endif /* DEBUG */ |
992 | 1024 | ||
993 | 1025 | ||
@@ -7951,6 +7983,7 @@ dotrap(void) | |||
7951 | pendingsig = 0; | 7983 | pendingsig = 0; |
7952 | xbarrier(); | 7984 | xbarrier(); |
7953 | 7985 | ||
7986 | TRACE(("dotrap entered\n")); | ||
7954 | for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) { | 7987 | for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) { |
7955 | int want_exexit; | 7988 | int want_exexit; |
7956 | char *t; | 7989 | char *t; |
@@ -7962,15 +7995,20 @@ dotrap(void) | |||
7962 | * don't upset it by resetting gotsig[SIGINT-1] */ | 7995 | * don't upset it by resetting gotsig[SIGINT-1] */ |
7963 | if (sig == SIGINT && !t) | 7996 | if (sig == SIGINT && !t) |
7964 | continue; | 7997 | continue; |
7998 | |||
7999 | TRACE(("sig %d is active, will run handler '%s'\n", sig, t)); | ||
7965 | *g = 0; | 8000 | *g = 0; |
7966 | if (!t) | 8001 | if (!t) |
7967 | continue; | 8002 | continue; |
7968 | want_exexit = evalstring(t, SKIPEVAL); | 8003 | want_exexit = evalstring(t, SKIPEVAL); |
7969 | exitstatus = savestatus; | 8004 | exitstatus = savestatus; |
7970 | if (want_exexit) | 8005 | if (want_exexit) { |
8006 | TRACE(("dotrap returns %d\n", skip)); | ||
7971 | return want_exexit; | 8007 | return want_exexit; |
8008 | } | ||
7972 | } | 8009 | } |
7973 | 8010 | ||
8011 | TRACE(("dotrap returns 0\n")); | ||
7974 | return 0; | 8012 | return 0; |
7975 | } | 8013 | } |
7976 | 8014 | ||
@@ -7997,22 +8035,27 @@ evaltree(union node *n, int flags) | |||
7997 | int checkexit = 0; | 8035 | int checkexit = 0; |
7998 | void (*evalfn)(union node *, int); | 8036 | void (*evalfn)(union node *, int); |
7999 | int status; | 8037 | int status; |
8038 | int int_level; | ||
8039 | |||
8040 | SAVE_INT(int_level); | ||
8000 | 8041 | ||
8001 | if (n == NULL) { | 8042 | if (n == NULL) { |
8002 | TRACE(("evaltree(NULL) called\n")); | 8043 | TRACE(("evaltree(NULL) called\n")); |
8003 | goto out1; | 8044 | goto out1; |
8004 | } | 8045 | } |
8005 | TRACE(("pid %d, evaltree(%p: %d, %d) called\n", | 8046 | TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags)); |
8006 | getpid(), n, n->type, flags)); | ||
8007 | 8047 | ||
8008 | exception_handler = &jmploc; | 8048 | exception_handler = &jmploc; |
8009 | { | 8049 | { |
8010 | int err = setjmp(jmploc.loc); | 8050 | int err = setjmp(jmploc.loc); |
8011 | if (err) { | 8051 | if (err) { |
8012 | /* if it was a signal, check for trap handlers */ | 8052 | /* if it was a signal, check for trap handlers */ |
8013 | if (exception_type == EXSIG) | 8053 | if (exception_type == EXSIG) { |
8054 | TRACE(("exception %d (EXSIG) in evaltree, err=%d\n", exception, err)); | ||
8014 | goto out; | 8055 | goto out; |
8056 | } | ||
8015 | /* continue on the way out */ | 8057 | /* continue on the way out */ |
8058 | TRACE(("exception %d in evaltree, propagating err=%d\n", exception, err)); | ||
8016 | exception_handler = savehandler; | 8059 | exception_handler = savehandler; |
8017 | longjmp(exception_handler->loc, err); | 8060 | longjmp(exception_handler->loc, err); |
8018 | } | 8061 | } |
@@ -8095,7 +8138,8 @@ evaltree(union node *n, int flags) | |||
8095 | if (exitstatus == 0) { | 8138 | if (exitstatus == 0) { |
8096 | n = n->nif.ifpart; | 8139 | n = n->nif.ifpart; |
8097 | goto evaln; | 8140 | goto evaln; |
8098 | } else if (n->nif.elsepart) { | 8141 | } |
8142 | if (n->nif.elsepart) { | ||
8099 | n = n->nif.elsepart; | 8143 | n = n->nif.elsepart; |
8100 | goto evaln; | 8144 | goto evaln; |
8101 | } | 8145 | } |
@@ -8121,6 +8165,9 @@ evaltree(union node *n, int flags) | |||
8121 | exexit: | 8165 | exexit: |
8122 | raise_exception(EXEXIT); | 8166 | raise_exception(EXEXIT); |
8123 | } | 8167 | } |
8168 | |||
8169 | RESTORE_INT(int_level); | ||
8170 | TRACE(("leaving evaltree (no interrupts)\n")); | ||
8124 | } | 8171 | } |
8125 | 8172 | ||
8126 | #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) | 8173 | #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) |
@@ -8998,6 +9045,7 @@ evalcommand(union node *cmd, int flags) | |||
8998 | if (forkshell(jp, cmd, FORK_FG) != 0) { | 9045 | if (forkshell(jp, cmd, FORK_FG) != 0) { |
8999 | exitstatus = waitforjob(jp); | 9046 | exitstatus = waitforjob(jp); |
9000 | INT_ON; | 9047 | INT_ON; |
9048 | TRACE(("forked child exited with %d\n", exitstatus)); | ||
9001 | break; | 9049 | break; |
9002 | } | 9050 | } |
9003 | FORCE_INT_ON; | 9051 | FORCE_INT_ON; |
@@ -13762,7 +13810,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13762 | exception_handler = &jmploc; | 13810 | exception_handler = &jmploc; |
13763 | #if DEBUG | 13811 | #if DEBUG |
13764 | opentrace(); | 13812 | opentrace(); |
13765 | trace_puts("Shell args: "); | 13813 | TRACE(("Shell args: ")); |
13766 | trace_puts_args(argv); | 13814 | trace_puts_args(argv); |
13767 | #endif | 13815 | #endif |
13768 | rootpid = getpid(); | 13816 | rootpid = getpid(); |
@@ -13847,14 +13895,6 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13847 | /* NOTREACHED */ | 13895 | /* NOTREACHED */ |
13848 | } | 13896 | } |
13849 | 13897 | ||
13850 | #if DEBUG | ||
13851 | const char *applet_name = "debug stuff usage"; | ||
13852 | int main(int argc, char **argv) | ||
13853 | { | ||
13854 | return ash_main(argc, argv); | ||
13855 | } | ||
13856 | #endif | ||
13857 | |||
13858 | 13898 | ||
13859 | /*- | 13899 | /*- |
13860 | * Copyright (c) 1989, 1991, 1993, 1994 | 13900 | * Copyright (c) 1989, 1991, 1993, 1994 |