From ead340a66039096c7b4bf12dcd65e189769c6653 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Mon, 18 Oct 2021 17:51:11 -0700 Subject: feat(rc): job control prototype working for basic commands --- sys/cmd/rc/wait.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) (limited to 'sys/cmd/rc/wait.c') diff --git a/sys/cmd/rc/wait.c b/sys/cmd/rc/wait.c index 06f9614..db586cb 100644 --- a/sys/cmd/rc/wait.c +++ b/sys/cmd/rc/wait.c @@ -1,3 +1,213 @@ #include "rc.h" + #include +// ----------------------------------------------------------------------- +// globals + +struct WaitMsg +{ + int pid; + ulong time[3]; + int status; + int signal; + int suspend; +}; + + +// ----------------------------------------------------------------------- +// internal + +static +int +await(int pid4, int opt, struct WaitMsg *msg) +{ + int pid, status, core; + struct rusage ru; + ulong u, s; + + /* event loop */ + for(;;){ + if((pid = wait4(pid4, &status, opt, &ru)) <= 0){ + msg->pid = 0; + perror("failed wait"); + return 0; + } + + u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000); + s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000); + + if(WIFEXITED(status)){ + msg->pid = pid; + msg->time[0] = u; + msg->time[1] = s; + msg->time[2] = u+s; + msg->status = WEXITSTATUS(status); + msg->signal = 0; + msg->suspend = 0; + + return 1; + } + + if(WIFSIGNALED(status)){ + msg->pid = pid; + msg->time[0] = u; + msg->time[1] = s; + msg->time[2] = u+s; + msg->status = WCOREDUMP(status); + msg->signal = 1; + msg->suspend = 0; + + return 1; + } + + if(WIFSTOPPED(status)){ + msg->pid = pid; + msg->time[0] = u; + msg->time[1] = s; + msg->time[2] = u+s; + msg->status = WSTOPSIG(status); + msg->signal = 0; + msg->suspend = 1; + + return 1; + } + } +} + +// ----------------------------------------------------------------------- +// exported + +void +clearwait(Thread *job) +{ + job->wait.len = 0; +} + +int +havewait(Thread *job, int pid) +{ + int i; + + for(i=0; iwait.len; i++) + if(job->wait.pid[i] == pid) + return 1; + return 0; +} + +void +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.pid[job->wait.len++] = pid; +} + +void +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]; + } + job->wait.len = w; +} + +int +waitall(Thread *job) +{ + Thread *t; + struct WaitMsg msg; + + while(job->wait.len && await(-job->pgid, WUNTRACED, &msg)){ + if(msg.pid == 0 && errno == ECHILD){ + perror("wait job"); + return 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); + } + } + delwait(t, msg.pid); + goto outer; + } + } + + perror("waitpid"); + return 0; + outer:; + } + + return 1; +} + +void +killzombies(void) +{ + Thread *job; + int index, status, pid; + + while((pid=waitpid(-1, &status, WNOHANG))>0){ + print(errio, "pid %d\n", pid); + flush(errio); + + job = getjob(pid, &index); + if(!job){ + perror("invalid pid"); + } + + job->flag.done = job->flag.stop = job->flag.again = 0; + + if(WIFEXITED(status)) + job->flag.done = 1; + if(WIFSTOPPED(status)) + job->flag.stop = 1; + if(WIFCONTINUED(status)) + job->flag.again = 1; + + if(job->flag.done){ + report(job,index); + deljob(job); + } + } +} + +#if 0 +int +waitfor(int pid) +{ + Thread *t; + struct WaitMsg w; + + if(pid >= 0 && !havewait(pid)) + return 0; + + while(await(-proc->pgid, WUNTRACED, &w)){ + delwait(w.pid); + if(w.pid == pid){ + if(w.signal) + print(errio, "pid[%d]: signal: %d\n", w.pid, w.status); + return 1; + } + for(t=proc->link; t; t=t->link){ + if(t->pid == w.pid) + t->pid = -1; + } + } + + return 0; +} +#endif -- cgit v1.2.1