aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/wait.c
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-18 17:51:11 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-18 17:51:11 -0700
commitead340a66039096c7b4bf12dcd65e189769c6653 (patch)
tree732594824f3e7951eecf0180792db2d24ff6d13e /sys/cmd/rc/wait.c
parentbf03074e346b004659196b6c17eee04dbffd3ac2 (diff)
feat(rc): job control prototype working for basic commands
Diffstat (limited to 'sys/cmd/rc/wait.c')
-rw-r--r--sys/cmd/rc/wait.c210
1 files changed, 210 insertions, 0 deletions
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 <sys/wait.h>
+// -----------------------------------------------------------------------
+// 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; i<job->wait.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