ash: [SIGNAL] Remove EXSIG
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 27 Oct 2016 19:09:01 +0000 (21:09 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 27 Oct 2016 19:13:49 +0000 (21:13 +0200)
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 <herbert@gondor.apana.org.au>
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 <herbert@gondor.apana.org.au>
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 <herbert@gondor.apana.org.au>
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 <vda.linux@googlemail.com>
shell/ash.c

index e21df329163231af551ca09cf42b28ef56e4aea3..b060d227a730c2b47f4d67da6ac446ebaf7f41ce 100644 (file)
@@ -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;