From 4b875708c13ec810e8fbd5721a68442f36a9210d Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 19 Mar 2009 13:30:04 +0000 Subject: [PATCH] ash: in dotrap(), do not clear gotsig[] for SIGINT if there is no handler for it, otherwise raise interrupt gets confused later. The rest are readability fixes. function old new delta evaltreenr 817 818 +1 evaltree 817 818 +1 evalstring 88 89 +1 cmdloop 420 419 -1 evalskip 4 1 -3 breakcmd 84 81 -3 ash_main 1382 1379 -3 evalloop 183 177 -6 evalfor 231 225 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/6 up/down: 3/-22) Total: -19 bytes --- shell/ash.c | 126 ++++++++++++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 57 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index f93d73735..9bb1d421e 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -162,6 +162,9 @@ struct globals_misc { // /* do we generate EXSIG events */ // int exsig; /* counter */ volatile int suppressint; /* counter */ +// TODO: rename +// pendingsig -> pending_sig +// intpending -> pending_int volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */ /* last pending signal */ volatile /*sig_atomic_t*/ smallint pendingsig; @@ -210,7 +213,7 @@ struct globals_misc { #define S_HARD_IGN 4 /* signal is ignored permenantly */ /* indicates specified signal received */ - char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ + uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */ char *trap[NSIG]; /* Rarely referenced stuff */ @@ -279,7 +282,7 @@ static int isdigit_str9(const char *str) /* * Called to raise an exception. Since C doesn't include exceptions, we * just do a longjmp to the exception handler. The type of exception is - * stored in the global variable "exception". + * stored in the global variable "exception_type". */ static void raise_exception(int) NORETURN; static void @@ -305,7 +308,7 @@ static void raise_interrupt(void) NORETURN; static void raise_interrupt(void) { - int i; + int ex_type; intpending = 0; /* Signal is not automatically unmasked after it is raised, @@ -313,16 +316,16 @@ raise_interrupt(void) sigprocmask_allsigs(SIG_UNBLOCK); /* pendingsig = 0; - now done in onsig() */ - i = EXSIG; + ex_type = EXSIG; if (gotsig[SIGINT - 1] && !trap[SIGINT]) { if (!(rootshell && iflag)) { /* Kill ourself with SIGINT */ signal(SIGINT, SIG_DFL); raise(SIGINT); } - i = EXINT; + ex_type = EXINT; } - raise_exception(i); + raise_exception(ex_type); /* NOTREACHED */ } @@ -366,37 +369,6 @@ force_int_on(void) raise_interrupt(); \ } while (0) -/* - * Ignore a signal. Avoids unnecessary system calls. - */ -static void -ignoresig(int signo) -{ - if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { - signal(signo, SIG_IGN); - } - sigmode[signo - 1] = S_HARD_IGN; -} - -/* - * Signal handler. Only one usage site - in setsignal() - */ -static void -onsig(int signo) -{ - gotsig[signo - 1] = 1; - - if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) { - if (!suppressint) { - pendingsig = 0; - raise_interrupt(); /* does not return */ - } - intpending = 1; - } else { - pendingsig = signo; - } -} - /* ============ Stdout/stderr output */ @@ -3287,6 +3259,39 @@ static smallint doing_jobctl; //references:8 static void setjobctl(int); #endif +/* + * Ignore a signal. + */ +static void +ignoresig(int signo) +{ + /* Avoid unnecessary system calls. Is it already SIG_IGNed? */ + if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { + /* No, need to do it */ + signal(signo, SIG_IGN); + } + sigmode[signo - 1] = S_HARD_IGN; +} + +/* + * Signal handler. Only one usage site - in setsignal() + */ +static void +onsig(int signo) +{ + gotsig[signo - 1] = 1; + + if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) { + if (!suppressint) { + pendingsig = 0; + raise_interrupt(); /* does not return */ + } + intpending = 1; + } else { + pendingsig = signo; + } +} + /* * Set the signal handler for the specified signal. The routine figures * out what it should be set to. @@ -7914,49 +7919,56 @@ defun(char *name, union node *func) INT_ON; } -static int evalskip; /* set if we are skipping commands */ -/* reasons for skipping commands (see comment on breakcmd routine) */ +/* Reasons for skipping commands (see comment on breakcmd routine) */ #define SKIPBREAK (1 << 0) #define SKIPCONT (1 << 1) #define SKIPFUNC (1 << 2) #define SKIPFILE (1 << 3) #define SKIPEVAL (1 << 4) +static smallint evalskip; /* set to SKIPxxx if we are skipping commands */ static int skipcount; /* number of levels to skip */ static int funcnest; /* depth of function calls */ static int loopnest; /* current loop nesting level */ -/* forward decl way out to parsing code - dotrap needs it */ +/* Forward decl way out to parsing code - dotrap needs it */ static int evalstring(char *s, int mask); -/* - * Called to execute a trap. Perhaps we should avoid entering new trap - * handlers while we are executing a trap handler. +/* Called to execute a trap. + * Single callsite - at the end of evaltree(). + * If we return non-zero, exaltree raises EXEXIT exception. + * + * Perhaps we should avoid entering new trap handlers + * while we are executing a trap handler. [is it a TODO?] */ static int dotrap(void) { - char *p; - char *q; - int i; - int savestatus; - int skip; + uint8_t *g; + int sig; + uint8_t savestatus; savestatus = exitstatus; pendingsig = 0; xbarrier(); - for (i = 1, q = gotsig; i < NSIG; i++, q++) { - if (!*q) - continue; - *q = '\0'; + for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) { + int want_exexit; + char *t; - p = trap[i]; - if (!p) + if (*g == 0) continue; - skip = evalstring(p, SKIPEVAL); + t = trap[sig]; + /* non-trapped SIGINT is handled separately by raise_interrupt, + * don't upset it by resetting gotsig[SIGINT-1] */ + if (sig == SIGINT && !t) + continue; + *g = 0; + if (!t) + continue; + want_exexit = evalstring(t, SKIPEVAL); exitstatus = savestatus; - if (skip) - return skip; + if (want_exexit) + return want_exexit; } return 0;