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
This commit is contained in:
Denis Vlasenko 2009-03-19 13:30:04 +00:00
parent 0354aba9a1
commit 4b875708c1

View File

@ -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;