From 47e3d475df6244a48b73421cd4210b64c392df8d Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 19 Oct 2021 09:35:59 -0700 Subject: feat(rc): cleaner process watching for each job --- sys/cmd/rc/wait.c | 94 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 30 deletions(-) (limited to 'sys/cmd/rc/wait.c') diff --git a/sys/cmd/rc/wait.c b/sys/cmd/rc/wait.c index db586cb..44ffb58 100644 --- a/sys/cmd/rc/wait.c +++ b/sys/cmd/rc/wait.c @@ -8,13 +8,11 @@ struct WaitMsg { int pid; + int type; ulong time[3]; int status; - int signal; - int suspend; }; - // ----------------------------------------------------------------------- // internal @@ -30,7 +28,7 @@ await(int pid4, int opt, struct WaitMsg *msg) for(;;){ if((pid = wait4(pid4, &status, opt, &ru)) <= 0){ msg->pid = 0; - perror("failed wait"); + perror("failed wait4"); return 0; } @@ -43,8 +41,7 @@ await(int pid4, int opt, struct WaitMsg *msg) msg->time[1] = s; msg->time[2] = u+s; msg->status = WEXITSTATUS(status); - msg->signal = 0; - msg->suspend = 0; + msg->type = PDone; return 1; } @@ -55,8 +52,7 @@ await(int pid4, int opt, struct WaitMsg *msg) msg->time[1] = s; msg->time[2] = u+s; msg->status = WCOREDUMP(status); - msg->signal = 1; - msg->suspend = 0; + msg->type = PSig; return 1; } @@ -67,14 +63,27 @@ await(int pid4, int opt, struct WaitMsg *msg) msg->time[1] = s; msg->time[2] = u+s; msg->status = WSTOPSIG(status); - msg->signal = 0; - msg->suspend = 1; + msg->type = PStop; return 1; } } } +static +int +shouldwait(Thread *job) +{ + int i; + + for(i=0; iwait.len; i++){ + if(job->wait.on[i].status == PRun) + return 1; + } + + return 0; +} + // ----------------------------------------------------------------------- // exported @@ -90,7 +99,7 @@ havewait(Thread *job, int pid) int i; for(i=0; iwait.len; i++) - if(job->wait.pid[i] == pid) + if(job->wait.on[i].pid == pid) return 1; return 0; } @@ -100,9 +109,10 @@ addwait(Thread *job, int pid) { if(job->wait.len == job->wait.cap){ job->wait.cap = job->wait.cap + 2; - job->wait.pid = erealloc(job->wait.pid, job->wait.cap*sizeof(*job->wait.pid)); + job->wait.on = erealloc(job->wait.on, job->wait.cap*sizeof(*job->wait.on)); } - job->wait.pid[job->wait.len++] = pid; + + job->wait.on[job->wait.len++] = (struct WaitItem){.pid=pid, .status=PRun}; } void @@ -111,8 +121,8 @@ delwait(Thread *job, int pid) int r, w; for(r=w=0; r < job->wait.len; r++){ - if(job->wait.pid[r] != pid) - job->wait.pid[w++] = job->wait.pid[r]; + if(job->wait.on[r].pid != pid) + job->wait.on[w++].pid = job->wait.on[r].pid; } job->wait.len = w; } @@ -120,36 +130,63 @@ delwait(Thread *job, int pid) int waitall(Thread *job) { + int i; Thread *t; struct WaitMsg msg; - while(job->wait.len && await(-job->pgid, WUNTRACED, &msg)){ - if(msg.pid == 0 && errno == ECHILD){ + while(shouldwait(job) && await(-job->pgid, WUNTRACED, &msg)){ + if(msg.pid == 0){ perror("wait job"); return 0; } + for(i=0; i < job->wait.len; i++){ + if(job->wait.on[i].pid == msg.pid){ + switch(msg.type){ + case PStop: + print(shell.err, "%d: suspended\n", msg.pid); + job->wait.status = PStop; + job->wait.on[i].status = PStop; + break; + + case PSig: + print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status); + /* fallthrough */ + case PDone: + job->wait.on[i].status = PDone; + delwait(job, msg.pid); + if(!job->wait.len) + job->wait.status = PDone; + break; + + default: + fatal("%d: unrecognized message type %d\n", msg.pid, msg.type); + } + break; + } + } + } +#if 0 for(t=job; t; t=t->link){ if(t->pid == msg.pid){ t->status = msg.status; - t->flag.stop = t->flag.done = t->flag.again = 0; if(msg.suspend){ t->flag.stop = 1; }else{ t->flag.done = 1; if(msg.signal){ - print(errio, "%d: terminated by signal %d\n", msg.pid, msg.status); + print(shell.err, "%d: terminated by signal %d\n", msg.pid, msg.status); } } delwait(t, msg.pid); goto outer; } } - perror("waitpid"); return 0; outer:; } +#endif return 1; } @@ -161,24 +198,21 @@ killzombies(void) int index, status, pid; while((pid=waitpid(-1, &status, WNOHANG))>0){ - print(errio, "pid %d\n", pid); - flush(errio); + print(shell.err, "found zombie pid %d\n", pid); + flush(shell.err); job = getjob(pid, &index); - if(!job){ + if(!job) perror("invalid pid"); - } - - job->flag.done = job->flag.stop = job->flag.again = 0; if(WIFEXITED(status)) - job->flag.done = 1; + job->wait.status = PDone; if(WIFSTOPPED(status)) - job->flag.stop = 1; + job->wait.status = PStop; if(WIFCONTINUED(status)) - job->flag.again = 1; + job->wait.status = PAgain; - if(job->flag.done){ + if(job->wait.status == PDone){ report(job,index); deljob(job); } -- cgit v1.2.1