aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/wait.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/wait.c')
-rw-r--r--sys/cmd/rc/wait.c94
1 files changed, 64 insertions, 30 deletions
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; i<job->wait.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; i<job->wait.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);
}