#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