aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-28 17:16:11 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-28 17:16:11 +0200
commit8f7b0248adca9a88351fd7f3dd208775242f3fe6 (patch)
tree813260e706183bee2bd28902587c4e1a7090a615
parentd81e9f5093b222369d510d0b1c0587a411e4c83e (diff)
downloadbusybox-w32-8f7b0248adca9a88351fd7f3dd208775242f3fe6.tar.gz
busybox-w32-8f7b0248adca9a88351fd7f3dd208775242f3fe6.tar.bz2
busybox-w32-8f7b0248adca9a88351fd7f3dd208775242f3fe6.zip
ash: use pause(), not sigsuspend(), in wait builtin
Same effect, smaller code function old new delta dowait 463 374 -89 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c57
1 files changed, 31 insertions, 26 deletions
diff --git a/shell/ash.c b/shell/ash.c
index fe112453c..fc1b5d927 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -296,8 +296,7 @@ struct globals_misc {
296 volatile int suppress_int; /* counter */ 296 volatile int suppress_int; /* counter */
297 volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */ 297 volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
298 volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */ 298 volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
299 /* last pending signal */ 299 volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
300 volatile /*sig_atomic_t*/ smallint pending_sig;
301 smallint exception_type; /* kind of exception (0..5) */ 300 smallint exception_type; /* kind of exception (0..5) */
302 /* exceptions */ 301 /* exceptions */
303#define EXINT 0 /* SIGINT received */ 302#define EXINT 0 /* SIGINT received */
@@ -3515,11 +3514,6 @@ setsignal(int signo)
3515#define CUR_RUNNING 1 3514#define CUR_RUNNING 1
3516#define CUR_STOPPED 0 3515#define CUR_STOPPED 0
3517 3516
3518/* mode flags for dowait */
3519#define DOWAIT_NONBLOCK 0
3520#define DOWAIT_BLOCK 1
3521#define DOWAIT_BLOCK_OR_SIG 2
3522
3523#if JOBS 3517#if JOBS
3524/* pgrp of shell on invocation */ 3518/* pgrp of shell on invocation */
3525static int initialpgrp; //references:2 3519static int initialpgrp; //references:2
@@ -3940,24 +3934,30 @@ sprint_status48(char *s, int status, int sigonly)
3940} 3934}
3941 3935
3942static int 3936static int
3943wait_block_or_sig(int *status, int wait_flags) 3937wait_block_or_sig(int *status)
3944{ 3938{
3945 sigset_t mask;
3946 int pid; 3939 int pid;
3947 3940
3948 do { 3941 do {
3949 /* Poll all children for changes in their state */ 3942 /* Poll all children for changes in their state */
3950 got_sigchld = 0; 3943 got_sigchld = 0;
3951 pid = waitpid(-1, status, wait_flags | WNOHANG); 3944 /* if job control is active, accept stopped processes too */
3945 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
3952 if (pid != 0) 3946 if (pid != 0)
3953 break; /* Error (e.g. EINTR) or pid */ 3947 break; /* Error (e.g. EINTR, ECHILD) or pid */
3954 3948
3955 /* No child is ready. Sleep until interesting signal is received */ 3949 /* Children exist, but none are ready. Sleep until interesting signal */
3950#if 0 /* dash does this */
3951 sigset_t mask;
3956 sigfillset(&mask); 3952 sigfillset(&mask);
3957 sigprocmask(SIG_SETMASK, &mask, &mask); 3953 sigprocmask(SIG_SETMASK, &mask, &mask);
3958 while (!got_sigchld && !pending_sig) 3954 while (!got_sigchld && !pending_sig)
3959 sigsuspend(&mask); 3955 sigsuspend(&mask);
3960 sigprocmask(SIG_SETMASK, &mask, NULL); 3956 sigprocmask(SIG_SETMASK, &mask, NULL);
3957#else
3958 while (!got_sigchld && !pending_sig)
3959 pause();
3960#endif
3961 3961
3962 /* If it was SIGCHLD, poll children again */ 3962 /* If it was SIGCHLD, poll children again */
3963 } while (got_sigchld); 3963 } while (got_sigchld);
@@ -3965,11 +3965,13 @@ wait_block_or_sig(int *status, int wait_flags)
3965 return pid; 3965 return pid;
3966} 3966}
3967 3967
3968#define DOWAIT_NONBLOCK 0
3969#define DOWAIT_BLOCK 1
3970#define DOWAIT_BLOCK_OR_SIG 2
3968 3971
3969static int 3972static int
3970dowait(int block, struct job *job) 3973dowait(int block, struct job *job)
3971{ 3974{
3972 int wait_flags;
3973 int pid; 3975 int pid;
3974 int status; 3976 int status;
3975 struct job *jp; 3977 struct job *jp;
@@ -3977,13 +3979,6 @@ dowait(int block, struct job *job)
3977 3979
3978 TRACE(("dowait(0x%x) called\n", block)); 3980 TRACE(("dowait(0x%x) called\n", block));
3979 3981
3980 wait_flags = 0;
3981 if (block == DOWAIT_NONBLOCK)
3982 wait_flags = WNOHANG;
3983 /* If job control is compiled in, we accept stopped processes too. */
3984 if (doing_jobctl)
3985 wait_flags |= WUNTRACED;
3986
3987 /* It's wrong to call waitpid() outside of INT_OFF region: 3982 /* It's wrong to call waitpid() outside of INT_OFF region:
3988 * signal can arrive just after syscall return and handler can 3983 * signal can arrive just after syscall return and handler can
3989 * longjmp away, losing stop/exit notification processing. 3984 * longjmp away, losing stop/exit notification processing.
@@ -3994,17 +3989,27 @@ dowait(int block, struct job *job)
3994 * in INT_OFF region: "wait" needs to wait for any running job 3989 * in INT_OFF region: "wait" needs to wait for any running job
3995 * to change state, but should exit on any trap too. 3990 * to change state, but should exit on any trap too.
3996 * In INT_OFF region, a signal just before syscall entry can set 3991 * In INT_OFF region, a signal just before syscall entry can set
3997 * pending_sig valiables, but we can't check them, and we would 3992 * pending_sig variables, but we can't check them, and we would
3998 * either enter a sleeping waitpid() (BUG), or need to busy-loop. 3993 * either enter a sleeping waitpid() (BUG), or need to busy-loop.
3994 *
3999 * Because of this, we run inside INT_OFF, but use a special routine 3995 * Because of this, we run inside INT_OFF, but use a special routine
4000 * which combines waitpid() and sigsuspend(). 3996 * which combines waitpid() and pause().
3997 * This is the reason why we need to have a handler for SIGCHLD:
3998 * SIG_DFL handler does not wake pause().
4001 */ 3999 */
4002 INT_OFF; 4000 INT_OFF;
4003 if (block == DOWAIT_BLOCK_OR_SIG) 4001 if (block == DOWAIT_BLOCK_OR_SIG) {
4004 pid = wait_block_or_sig(&status, wait_flags); 4002 pid = wait_block_or_sig(&status);
4005 else 4003 } else {
4006 /* NB: _not_ safe_waitpid, we need to detect EINTR. */ 4004 int wait_flags = 0;
4005 if (block == DOWAIT_NONBLOCK)
4006 wait_flags = WNOHANG;
4007 /* if job control is active, accept stopped processes too */
4008 if (doing_jobctl)
4009 wait_flags |= WUNTRACED;
4010 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4007 pid = waitpid(-1, &status, wait_flags); 4011 pid = waitpid(-1, &status, wait_flags);
4012 }
4008 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", 4013 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4009 pid, status, errno, strerror(errno))); 4014 pid, status, errno, strerror(errno)));
4010 if (pid <= 0) 4015 if (pid <= 0)