aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-27 21:09:01 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-27 21:13:49 +0200
commitc0663c7cd218e23a9c256491c787203a07efb666 (patch)
treee8c9671f02686f941bd81df34fc73db41452f129
parent69188110146198c2c3fe7344c7d11dfac8891245 (diff)
downloadbusybox-w32-c0663c7cd218e23a9c256491c787203a07efb666.tar.gz
busybox-w32-c0663c7cd218e23a9c256491c787203a07efb666.tar.bz2
busybox-w32-c0663c7cd218e23a9c256491c787203a07efb666.zip
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 <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>
-rw-r--r--shell/ash.c87
1 files 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 {
302#define EXINT 0 /* SIGINT received */ 302#define EXINT 0 /* SIGINT received */
303#define EXERROR 1 /* a generic error */ 303#define EXERROR 1 /* a generic error */
304#define EXEXIT 4 /* exit the shell */ 304#define EXEXIT 4 /* exit the shell */
305#define EXSIG 5 /* trapped signal in wait(1) */
306 305
307 smallint isloginsh; 306 smallint isloginsh;
308 char nullstr[1]; /* zero length string */ 307 char nullstr[1]; /* zero length string */
@@ -482,26 +481,20 @@ static void raise_interrupt(void) NORETURN;
482static void 481static void
483raise_interrupt(void) 482raise_interrupt(void)
484{ 483{
485 int ex_type;
486
487 pending_int = 0; 484 pending_int = 0;
488 /* Signal is not automatically unmasked after it is raised, 485 /* Signal is not automatically unmasked after it is raised,
489 * do it ourself - unmask all signals */ 486 * do it ourself - unmask all signals */
490 sigprocmask_allsigs(SIG_UNBLOCK); 487 sigprocmask_allsigs(SIG_UNBLOCK);
491 /* pending_sig = 0; - now done in signal_handler() */ 488 /* pending_sig = 0; - now done in signal_handler() */
492 489
493 ex_type = EXSIG; 490 if (!(rootshell && iflag)) {
494 if (gotsig[SIGINT - 1] && !trap[SIGINT]) { 491 /* Kill ourself with SIGINT */
495 if (!(rootshell && iflag)) { 492 signal(SIGINT, SIG_DFL);
496 /* Kill ourself with SIGINT */ 493 raise(SIGINT);
497 signal(SIGINT, SIG_DFL);
498 raise(SIGINT);
499 }
500 ex_type = EXINT;
501 } 494 }
502 /* bash: ^C even on empty command line sets $? */ 495 /* bash: ^C even on empty command line sets $? */
503 exitstatus = SIGINT + 128; 496 exitstatus = SIGINT + 128;
504 raise_exception(ex_type); 497 raise_exception(EXINT);
505 /* NOTREACHED */ 498 /* NOTREACHED */
506} 499}
507#if DEBUG 500#if DEBUG
@@ -4201,9 +4194,6 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4201 int retval; 4194 int retval;
4202 struct job *jp; 4195 struct job *jp;
4203 4196
4204 if (pending_sig)
4205 raise_exception(EXSIG);
4206
4207 nextopt(nullstr); 4197 nextopt(nullstr);
4208 retval = 0; 4198 retval = 0;
4209 4199
@@ -4220,7 +4210,6 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4220 jp->waited = 1; 4210 jp->waited = 1;
4221 jp = jp->prev_job; 4211 jp = jp->prev_job;
4222 } 4212 }
4223 dowait(DOWAIT_BLOCK, NULL);
4224 /* man bash: 4213 /* man bash:
4225 * "When bash is waiting for an asynchronous command via 4214 * "When bash is waiting for an asynchronous command via
4226 * the wait builtin, the reception of a signal for which a trap 4215 * the wait builtin, the reception of a signal for which a trap
@@ -4228,8 +4217,13 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4228 * with an exit status greater than 128, immediately after which 4217 * with an exit status greater than 128, immediately after which
4229 * the trap is executed." 4218 * the trap is executed."
4230 */ 4219 */
4220 dowait(DOWAIT_BLOCK, NULL); ///DOWAIT_WAITCMD
4221 /* if child sends us a signal *and immediately exits*,
4222 * dowait() returns pid > 0. Check this case,
4223 * not "if (dowait() < 0)"!
4224 */
4231 if (pending_sig) 4225 if (pending_sig)
4232 raise_exception(EXSIG); 4226 goto sigout;
4233 } 4227 }
4234 } 4228 }
4235 4229
@@ -4250,9 +4244,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4250 } 4244 }
4251 /* loop until process terminated or stopped */ 4245 /* loop until process terminated or stopped */
4252 while (job->state == JOBRUNNING) { 4246 while (job->state == JOBRUNNING) {
4253 pid_t pid = dowait(DOWAIT_BLOCK, NULL); 4247 dowait(DOWAIT_BLOCK, NULL); ///DOWAIT_WAITCMD
4254 if (pid <= 0 && pending_sig) 4248 if (pending_sig)
4255 raise_exception(EXSIG); 4249 goto sigout;
4256 } 4250 }
4257 job->waited = 1; 4251 job->waited = 1;
4258 retval = getstatus(job); 4252 retval = getstatus(job);
@@ -4261,6 +4255,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4261 4255
4262 ret: 4256 ret:
4263 return retval; 4257 return retval;
4258 sigout:
4259 retval = 128 + pending_sig;
4260 return retval;
4264} 4261}
4265 4262
4266static struct job * 4263static struct job *
@@ -8475,41 +8472,18 @@ static void prehash(union node *);
8475static int 8472static int
8476evaltree(union node *n, int flags) 8473evaltree(union node *n, int flags)
8477{ 8474{
8478 struct jmploc *volatile savehandler = exception_handler;
8479 struct jmploc jmploc;
8480 int checkexit = 0; 8475 int checkexit = 0;
8481 int (*evalfn)(union node *, int); 8476 int (*evalfn)(union node *, int);
8482 int status = 0; 8477 int status = 0;
8483 int int_level;
8484
8485 SAVE_INT(int_level);
8486 8478
8487 if (n == NULL) { 8479 if (n == NULL) {
8488 TRACE(("evaltree(NULL) called\n")); 8480 TRACE(("evaltree(NULL) called\n"));
8489 goto out1; 8481 goto out;
8490 } 8482 }
8491 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags)); 8483 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8492 8484
8493 dotrap(); 8485 dotrap();
8494 8486
8495 exception_handler = &jmploc;
8496 {
8497 int err = setjmp(jmploc.loc);
8498 if (err) {
8499 /* if it was a signal, check for trap handlers */
8500 if (exception_type == EXSIG) {
8501 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8502 exception_type, err));
8503 goto out;
8504 }
8505 /* continue on the way out */
8506 TRACE(("exception %d in evaltree, propagating err=%d\n",
8507 exception_type, err));
8508 exception_handler = savehandler;
8509 longjmp(exception_handler->loc, err);
8510 }
8511 }
8512
8513 switch (n->type) { 8487 switch (n->type) {
8514 default: 8488 default:
8515#if DEBUG 8489#if DEBUG
@@ -8600,11 +8574,7 @@ evaltree(union node *n, int flags)
8600 exitstatus = status; 8574 exitstatus = status;
8601 break; 8575 break;
8602 } 8576 }
8603
8604 out: 8577 out:
8605 exception_handler = savehandler;
8606
8607 out1:
8608 /* Order of checks below is important: 8578 /* Order of checks below is important:
8609 * signal handlers trigger before exit caused by "set -e". 8579 * signal handlers trigger before exit caused by "set -e".
8610 */ 8580 */
@@ -8615,9 +8585,7 @@ evaltree(union node *n, int flags)
8615 if (flags & EV_EXIT) 8585 if (flags & EV_EXIT)
8616 raise_exception(EXEXIT); 8586 raise_exception(EXEXIT);
8617 8587
8618 RESTORE_INT(int_level);
8619 TRACE(("leaving evaltree (no interrupts)\n")); 8588 TRACE(("leaving evaltree (no interrupts)\n"));
8620
8621 return exitstatus; 8589 return exitstatus;
8622} 8590}
8623 8591
@@ -9574,21 +9542,12 @@ evalcommand(union node *cmd, int flags)
9574 dowait(DOWAIT_NONBLOCK, NULL); 9542 dowait(DOWAIT_NONBLOCK, NULL);
9575 9543
9576 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { 9544 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9577 int exit_status; 9545 if (exception_type == EXERROR && spclbltin <= 0) {
9578 int i = exception_type; 9546 FORCE_INT_ON;
9579 if (i == EXEXIT) 9547 break;
9580 goto raise;
9581 exit_status = 2;
9582 if (i == EXINT)
9583 exit_status = 128 + SIGINT;
9584 if (i == EXSIG)
9585 exit_status = 128 + pending_sig;
9586 exitstatus = exit_status;
9587 if (i == EXINT || spclbltin > 0) {
9588 raise:
9589 longjmp(exception_handler->loc, 1);
9590 } 9548 }
9591 FORCE_INT_ON; 9549 raise:
9550 longjmp(exception_handler->loc, 1);
9592 } 9551 }
9593 goto readstatus; 9552 goto readstatus;
9594 9553