aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-08-10 23:39:44 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-08-10 23:39:44 +0200
commitea2022efb32661e33ec43f3cd9f5cae8bc2b9547 (patch)
treefed618f1ca27f007925679380504ca87f8e6ad8d /shell
parentf6fb3c603a330d8b9b4910763f8fcee0fa90bba3 (diff)
downloadbusybox-w32-ea2022efb32661e33ec43f3cd9f5cae8bc2b9547.tar.gz
busybox-w32-ea2022efb32661e33ec43f3cd9f5cae8bc2b9547.tar.bz2
busybox-w32-ea2022efb32661e33ec43f3cd9f5cae8bc2b9547.zip
ash: converge waiting code to dash in its form, add comments, no code changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c56
1 files 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)
4412 return s - os; 4412 return s - os;
4413} 4413}
4414 4414
4415#define DOWAIT_NONBLOCK 0 4415/* Inside dowait(): */
4416#define DOWAIT_BLOCK 1 4416#define DOWAIT_NONBLOCK 0 /* waitpid() will use WNOHANG and won't wait for signals */
4417#define DOWAIT_BLOCK_OR_SIG 2 4417#define DOWAIT_BLOCK 1 /* waitpid() will NOT use WNOHANG */
4418#define DOWAIT_CHILD_OR_SIG 2 /* waitpid() will use WNOHANG and if got 0, will wait for signals, then loop back */
4418#if BASH_WAIT_N 4419#if BASH_WAIT_N
4419# define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */ 4420# define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */
4420#endif 4421#endif
4421 4422
4422static int 4423static int
@@ -4437,9 +4438,16 @@ waitproc(int block, int *status)
4437 err = waitpid(-1, status, flags); 4438 err = waitpid(-1, status, flags);
4438 while (err < 0 && errno == EINTR); 4439 while (err < 0 && errno == EINTR);
4439 4440
4441 /* Return if error (for example, ECHILD); or if pid found;
4442 * or if "block" is DOWAIT_NONBLOCK (=0), in this case return -1.
4443 */
4440 if (err || (err = -!block)) 4444 if (err || (err = -!block))
4441 break; 4445 break;
4442 4446
4447 /* "block" is DOWAIT_CHILD_OR_SIG. All children are running
4448 * (waitpid(WNOHAG) above returned 0), wait for signals:
4449 */
4450
4443 //simpler, but unsafe: a signal can set pending_sig after check, but before pause(): 4451 //simpler, but unsafe: a signal can set pending_sig after check, but before pause():
4444 //while (!gotsigchld && !pending_sig) 4452 //while (!gotsigchld && !pending_sig)
4445 // pause(); 4453 // pause();
@@ -4451,12 +4459,12 @@ waitproc(int block, int *status)
4451 4459
4452 sigclearmask(); 4460 sigclearmask();
4453 } while (gotsigchld); 4461 } while (gotsigchld);
4462 /* If we fall off the loop, err is 0, which means we got a !SIGCHLD signal */
4454 4463
4455 return err; 4464 return err;
4456} 4465}
4457 4466
4458static int 4467static int waitone(int block, struct job *job)
4459waitone(int block, struct job *job)
4460{ 4468{
4461 int pid; 4469 int pid;
4462 int status; 4470 int status;
@@ -4495,32 +4503,30 @@ waitone(int block, struct job *job)
4495 4503
4496 for (jp = curjob; jp; jp = jp->prev_job) { 4504 for (jp = curjob; jp; jp = jp->prev_job) {
4497 int jobstate; 4505 int jobstate;
4498 struct procstat *ps; 4506 struct procstat *sp;
4499 struct procstat *psend; 4507 struct procstat *spend;
4500 if (jp->state == JOBDONE) 4508 if (jp->state == JOBDONE)
4501 continue; 4509 continue;
4502 jobstate = JOBDONE; 4510 jobstate = JOBDONE;
4503 ps = jp->ps; 4511 spend = jp->ps + jp->nprocs;
4504 psend = ps + jp->nprocs; 4512 sp = jp->ps;
4505 do { 4513 do {
4506 if (ps->ps_pid == pid) { 4514 if (sp->ps_pid == pid) {
4507 TRACE(("Job %d: changing status of proc %d " 4515 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->ps_status, status));
4508 "from 0x%x to 0x%x\n", 4516 sp->ps_status = status;
4509 jobno(jp), pid, ps->ps_status, status));
4510 ps->ps_status = status;
4511 thisjob = jp; 4517 thisjob = jp;
4512 } 4518 }
4513 if (ps->ps_status == -1) 4519 if (sp->ps_status == -1)
4514 jobstate = JOBRUNNING; 4520 jobstate = JOBRUNNING;
4515#if JOBS 4521#if JOBS
4516 if (jobstate == JOBRUNNING) 4522 if (jobstate == JOBRUNNING)
4517 continue; 4523 continue;
4518 if (WIFSTOPPED(ps->ps_status)) { 4524 if (WIFSTOPPED(sp->ps_status)) {
4519 jp->stopstatus = ps->ps_status; 4525 jp->stopstatus = sp->ps_status;
4520 jobstate = JOBSTOPPED; 4526 jobstate = JOBSTOPPED;
4521 } 4527 }
4522#endif 4528#endif
4523 } while (++ps < psend); 4529 } while (++sp < spend);
4524 if (!thisjob) 4530 if (!thisjob)
4525 continue; 4531 continue;
4526 4532
@@ -4532,8 +4538,7 @@ waitone(int block, struct job *job)
4532 */ 4538 */
4533 thisjob->changed = 1; 4539 thisjob->changed = 1;
4534 if (thisjob->state != jobstate) { 4540 if (thisjob->state != jobstate) {
4535 TRACE(("Job %d: changing state from %d to %d\n", 4541 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, jobstate));
4536 jobno(thisjob), thisjob->state, jobstate));
4537 thisjob->state = jobstate; 4542 thisjob->state = jobstate;
4538#if JOBS 4543#if JOBS
4539 if (jobstate == JOBSTOPPED) 4544 if (jobstate == JOBSTOPPED)
@@ -4568,8 +4573,7 @@ waitone(int block, struct job *job)
4568 return pid; 4573 return pid;
4569} 4574}
4570 4575
4571static int 4576static int dowait(int block, struct job *jp)
4572dowait(int block, struct job *jp)
4573{ 4577{
4574 smallint gotchld = *(volatile smallint *)&gotsigchld; 4578 smallint gotchld = *(volatile smallint *)&gotsigchld;
4575 int rpid; 4579 int rpid;
@@ -4795,9 +4799,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4795 * the trap is executed." 4799 * the trap is executed."
4796 */ 4800 */
4797#if BASH_WAIT_N 4801#if BASH_WAIT_N
4798 status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL); 4802 status = dowait(DOWAIT_CHILD_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4799#else 4803#else
4800 dowait(DOWAIT_BLOCK_OR_SIG, NULL); 4804 dowait(DOWAIT_CHILD_OR_SIG, NULL);
4801#endif 4805#endif
4802 /* if child sends us a signal *and immediately exits*, 4806 /* if child sends us a signal *and immediately exits*,
4803 * dowait() returns pid > 0. Check this case, 4807 * dowait() returns pid > 0. Check this case,
@@ -4838,7 +4842,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4838 job = getjob(*argv, 0); 4842 job = getjob(*argv, 0);
4839 } 4843 }
4840 /* loop until process terminated or stopped */ 4844 /* loop until process terminated or stopped */
4841 dowait(DOWAIT_BLOCK_OR_SIG, job); 4845 dowait(DOWAIT_CHILD_OR_SIG, job);
4842 if (pending_sig) 4846 if (pending_sig)
4843 goto sigout; 4847 goto sigout;
4844 job->waited = 1; 4848 job->waited = 1;