ash: converge waiting code to dash in its form, add comments, no code changes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2025-08-10 23:39:44 +02:00
parent f6fb3c603a
commit ea2022efb3

View file

@ -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;