From ea2022efb32661e33ec43f3cd9f5cae8bc2b9547 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 10 Aug 2025 23:39:44 +0200 Subject: [PATCH] ash: converge waiting code to dash in its form, add comments, no code changes Signed-off-by: Denys Vlasenko --- shell/ash.c | 56 ++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 14c59a769..ad1b9fd9f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4412,11 +4412,12 @@ sprint_status48(char *os, int status, int sigonly) return s - os; } -#define DOWAIT_NONBLOCK 0 -#define DOWAIT_BLOCK 1 -#define DOWAIT_BLOCK_OR_SIG 2 +/* Inside dowait(): */ +#define DOWAIT_NONBLOCK 0 /* waitpid() will use WNOHANG and won't wait for signals */ +#define DOWAIT_BLOCK 1 /* waitpid() will NOT use WNOHANG */ +#define DOWAIT_CHILD_OR_SIG 2 /* waitpid() will use WNOHANG and if got 0, will wait for signals, then loop back */ #if BASH_WAIT_N -# define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */ +# define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */ #endif static int @@ -4437,9 +4438,16 @@ waitproc(int block, int *status) err = waitpid(-1, status, flags); while (err < 0 && errno == EINTR); + /* Return if error (for example, ECHILD); or if pid found; + * or if "block" is DOWAIT_NONBLOCK (=0), in this case return -1. + */ if (err || (err = -!block)) break; + /* "block" is DOWAIT_CHILD_OR_SIG. All children are running + * (waitpid(WNOHAG) above returned 0), wait for signals: + */ + //simpler, but unsafe: a signal can set pending_sig after check, but before pause(): //while (!gotsigchld && !pending_sig) // pause(); @@ -4451,12 +4459,12 @@ waitproc(int block, int *status) sigclearmask(); } while (gotsigchld); + /* If we fall off the loop, err is 0, which means we got a !SIGCHLD signal */ return err; } -static int -waitone(int block, struct job *job) +static int waitone(int block, struct job *job) { int pid; int status; @@ -4495,32 +4503,30 @@ waitone(int block, struct job *job) for (jp = curjob; jp; jp = jp->prev_job) { int jobstate; - struct procstat *ps; - struct procstat *psend; + struct procstat *sp; + struct procstat *spend; if (jp->state == JOBDONE) continue; jobstate = JOBDONE; - ps = jp->ps; - psend = ps + jp->nprocs; + spend = jp->ps + jp->nprocs; + sp = jp->ps; do { - if (ps->ps_pid == pid) { - TRACE(("Job %d: changing status of proc %d " - "from 0x%x to 0x%x\n", - jobno(jp), pid, ps->ps_status, status)); - ps->ps_status = status; + if (sp->ps_pid == pid) { + TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->ps_status, status)); + sp->ps_status = status; thisjob = jp; } - if (ps->ps_status == -1) + if (sp->ps_status == -1) jobstate = JOBRUNNING; #if JOBS if (jobstate == JOBRUNNING) continue; - if (WIFSTOPPED(ps->ps_status)) { - jp->stopstatus = ps->ps_status; + if (WIFSTOPPED(sp->ps_status)) { + jp->stopstatus = sp->ps_status; jobstate = JOBSTOPPED; } #endif - } while (++ps < psend); + } while (++sp < spend); if (!thisjob) continue; @@ -4532,8 +4538,7 @@ waitone(int block, struct job *job) */ thisjob->changed = 1; if (thisjob->state != jobstate) { - TRACE(("Job %d: changing state from %d to %d\n", - jobno(thisjob), thisjob->state, jobstate)); + TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, jobstate)); thisjob->state = jobstate; #if JOBS if (jobstate == JOBSTOPPED) @@ -4568,8 +4573,7 @@ waitone(int block, struct job *job) return pid; } -static int -dowait(int block, struct job *jp) +static int dowait(int block, struct job *jp) { smallint gotchld = *(volatile smallint *)&gotsigchld; int rpid; @@ -4795,9 +4799,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv) * the trap is executed." */ #if BASH_WAIT_N - status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL); + status = dowait(DOWAIT_CHILD_OR_SIG | DOWAIT_JOBSTATUS, NULL); #else - dowait(DOWAIT_BLOCK_OR_SIG, NULL); + dowait(DOWAIT_CHILD_OR_SIG, NULL); #endif /* if child sends us a signal *and immediately exits*, * dowait() returns pid > 0. Check this case, @@ -4838,7 +4842,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv) job = getjob(*argv, 0); } /* loop until process terminated or stopped */ - dowait(DOWAIT_BLOCK_OR_SIG, job); + dowait(DOWAIT_CHILD_OR_SIG, job); if (pending_sig) goto sigout; job->waited = 1;