From c0663c7cd218e23a9c256491c787203a07efb666 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Oct 2016 21:09:01 +0200 Subject: ash: [SIGNAL] Remove EXSIG Upstream commit 1: Date: Sun, 22 Feb 2009 18:16:13 +0800 [SIGNAL] Remove EXSIG Now that waitcmd no longer uses EXSIG we can remove it. Signed-off-by: Herbert Xu Upstream commit 2: Date: Thu, 2 Oct 2014 21:07:55 +0800 [ERROR] Set exitstatus in onint Currently the exit status when we receive SIGINT is set in evalcommand which means that it doesn't always get set. For example, if you press CTRL-C at the prompt of an interactive dash, the exit status is not set to 130 as it is in many other Bourne shells. This patch fixes this by moving the setting of the exit status into onint which also simplifies evalcommand. Signed-off-by: Herbert Xu Upstream commit 3: Date: Fri, 3 Oct 2014 14:07:07 +0800 [EVAL] Do not clobber exitstatus in evalcommand All originators of EXERROR have been setting the exitstatus for a while now. So it is no longer appropriate to set it explicitly in evalcommand. In fact doing so may cause the original exitstatus to be lost. Signed-off-by: Herbert Xu Last three coomits: function old new delta waitcmd 186 224 +38 dowait 276 284 +8 waitforjob 104 107 +3 localcmd 348 350 +2 showjobs 64 61 -3 forkshell 263 260 -3 raise_interrupt 93 67 -26 blocking_wait_with_raise_on_sig 40 - -40 evalcommand 1264 1208 -56 evaltree 809 498 -311 Signed-off-by: Denys Vlasenko --- shell/ash.c | 87 ++++++++++++++++--------------------------------------------- 1 file changed, 23 insertions(+), 64 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index e21df3291..b060d227a 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -302,7 +302,6 @@ struct globals_misc { #define EXINT 0 /* SIGINT received */ #define EXERROR 1 /* a generic error */ #define EXEXIT 4 /* exit the shell */ -#define EXSIG 5 /* trapped signal in wait(1) */ smallint isloginsh; char nullstr[1]; /* zero length string */ @@ -482,26 +481,20 @@ static void raise_interrupt(void) NORETURN; static void raise_interrupt(void) { - int ex_type; - pending_int = 0; /* Signal is not automatically unmasked after it is raised, * do it ourself - unmask all signals */ sigprocmask_allsigs(SIG_UNBLOCK); /* pending_sig = 0; - now done in signal_handler() */ - ex_type = EXSIG; - if (gotsig[SIGINT - 1] && !trap[SIGINT]) { - if (!(rootshell && iflag)) { - /* Kill ourself with SIGINT */ - signal(SIGINT, SIG_DFL); - raise(SIGINT); - } - ex_type = EXINT; + if (!(rootshell && iflag)) { + /* Kill ourself with SIGINT */ + signal(SIGINT, SIG_DFL); + raise(SIGINT); } /* bash: ^C even on empty command line sets $? */ exitstatus = SIGINT + 128; - raise_exception(ex_type); + raise_exception(EXINT); /* NOTREACHED */ } #if DEBUG @@ -4201,9 +4194,6 @@ waitcmd(int argc UNUSED_PARAM, char **argv) int retval; struct job *jp; - if (pending_sig) - raise_exception(EXSIG); - nextopt(nullstr); retval = 0; @@ -4220,16 +4210,20 @@ waitcmd(int argc UNUSED_PARAM, char **argv) jp->waited = 1; jp = jp->prev_job; } - dowait(DOWAIT_BLOCK, NULL); /* man bash: * "When bash is waiting for an asynchronous command via * the wait builtin, the reception of a signal for which a trap * has been set will cause the wait builtin to return immediately * with an exit status greater than 128, immediately after which * the trap is executed." + */ + dowait(DOWAIT_BLOCK, NULL); ///DOWAIT_WAITCMD + /* if child sends us a signal *and immediately exits*, + * dowait() returns pid > 0. Check this case, + * not "if (dowait() < 0)"! */ if (pending_sig) - raise_exception(EXSIG); + goto sigout; } } @@ -4250,9 +4244,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv) } /* loop until process terminated or stopped */ while (job->state == JOBRUNNING) { - pid_t pid = dowait(DOWAIT_BLOCK, NULL); - if (pid <= 0 && pending_sig) - raise_exception(EXSIG); + dowait(DOWAIT_BLOCK, NULL); ///DOWAIT_WAITCMD + if (pending_sig) + goto sigout; } job->waited = 1; retval = getstatus(job); @@ -4261,6 +4255,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv) ret: return retval; + sigout: + retval = 128 + pending_sig; + return retval; } static struct job * @@ -8475,41 +8472,18 @@ static void prehash(union node *); static int evaltree(union node *n, int flags) { - struct jmploc *volatile savehandler = exception_handler; - struct jmploc jmploc; int checkexit = 0; int (*evalfn)(union node *, int); int status = 0; - int int_level; - - SAVE_INT(int_level); if (n == NULL) { TRACE(("evaltree(NULL) called\n")); - goto out1; + goto out; } TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags)); dotrap(); - exception_handler = &jmploc; - { - int err = setjmp(jmploc.loc); - if (err) { - /* if it was a signal, check for trap handlers */ - if (exception_type == EXSIG) { - TRACE(("exception %d (EXSIG) in evaltree, err=%d\n", - exception_type, err)); - goto out; - } - /* continue on the way out */ - TRACE(("exception %d in evaltree, propagating err=%d\n", - exception_type, err)); - exception_handler = savehandler; - longjmp(exception_handler->loc, err); - } - } - switch (n->type) { default: #if DEBUG @@ -8600,11 +8574,7 @@ evaltree(union node *n, int flags) exitstatus = status; break; } - out: - exception_handler = savehandler; - - out1: /* Order of checks below is important: * signal handlers trigger before exit caused by "set -e". */ @@ -8615,9 +8585,7 @@ evaltree(union node *n, int flags) if (flags & EV_EXIT) raise_exception(EXEXIT); - RESTORE_INT(int_level); TRACE(("leaving evaltree (no interrupts)\n")); - return exitstatus; } @@ -9574,21 +9542,12 @@ evalcommand(union node *cmd, int flags) dowait(DOWAIT_NONBLOCK, NULL); if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { - int exit_status; - int i = exception_type; - if (i == EXEXIT) - goto raise; - exit_status = 2; - if (i == EXINT) - exit_status = 128 + SIGINT; - if (i == EXSIG) - exit_status = 128 + pending_sig; - exitstatus = exit_status; - if (i == EXINT || spclbltin > 0) { - raise: - longjmp(exception_handler->loc, 1); + if (exception_type == EXERROR && spclbltin <= 0) { + FORCE_INT_ON; + break; } - FORCE_INT_ON; + raise: + longjmp(exception_handler->loc, 1); } goto readstatus; -- cgit v1.2.3