diff options
| author | cinap_lenrek <cinap_lenrek@felloff.net> | 2013-12-07 07:17:32 +0100 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2013-12-07 07:17:32 +0100 |
| commit | 77611280935dfbd7b976fd9340bf8593bf4320f1 (patch) | |
| tree | b9b7a39d8057fd30fcb6fca674356db4df15cd4f | |
| parent | 4fd55abb8e6dc11b257699cbd095fa5ef60e1ece (diff) | |
| download | plan9front-77611280935dfbd7b976fd9340bf8593bf4320f1.tar.xz | |
devproc: make sure /proc/n/wait waits for the right process children
theres a race when we wait for a process children and that
process exits before we sleep().
| -rw-r--r-- | sys/src/9/port/devproc.c | 29 | ||||
| -rw-r--r-- | sys/src/9/port/portfns.h | 1 | ||||
| -rw-r--r-- | sys/src/9/port/proc.c | 2 |
3 files changed, 22 insertions, 10 deletions
diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c index e5fd24671..86e2ceba3 100644 --- a/sys/src/9/port/devproc.c +++ b/sys/src/9/port/devproc.c @@ -680,12 +680,23 @@ eventsavailable(void *) return tproduced > tconsumed; } +static int +prochaswaitq(void *x) +{ + Chan *c; + Proc *p; + + c = (Chan *)x; + p = proctab(SLOT(c->qid)); + return p->pid != PID(c->qid) || p->waitq != 0; +} + static long procread(Chan *c, void *va, long n, vlong off) { /* NSEG*32 was too small for worst cases */ char *a, flag[10], *sps, *srv, statbuf[NSEG*64]; - int i, j, m, navail, ne, pid, rsize; + int i, j, m, navail, ne, rsize; long l; uchar *rptr; ulong offset; @@ -924,18 +935,19 @@ procread(Chan *c, void *va, long n, vlong off) } lock(&p->exl); - pid = p->pid; - while(p->waitq == 0) { + while(p->waitq == 0 && p->pid == PID(c->qid)) { if(up == p && p->nchild == 0) { unlock(&p->exl); error(Enochild); } unlock(&p->exl); - sleep(&p->waitr, haswaitq, p); - if(p->pid != pid) - error(Eprocdied); + sleep(&p->waitr, prochaswaitq, c); lock(&p->exl); } + if(p->pid != PID(c->qid)){ + unlock(&p->exl); + error(Eprocdied); + } wq = p->waitq; p->waitq = wq->next; p->nwait--; @@ -1229,11 +1241,12 @@ procstopwait(Proc *p, int ctl) error(Einuse); if(procstopped(p) || p->state == Broken) return; - + pid = p->pid; + if(pid == 0) + error(Eprocdied); if(ctl != 0) p->procctl = ctl; p->pdbg = up; - pid = p->pid; qunlock(&p->debug); up->psstate = "Stopwait"; if(waserror()) { diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index ffeb7315a..6b27eaf2c 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -124,7 +124,6 @@ ulong getmalloctag(void*); ulong getrealloctag(void*); void gotolabel(Label*); char* getconfenv(void); -int haswaitq(void*); long hostdomainwrite(char*, int); long hostownerwrite(char*, int); void hzsched(void); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 838ad49a1..ed549fb75 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1205,7 +1205,7 @@ pexit(char *exitstr, int freemem) panic("pexit"); } -int +static int haswaitq(void *x) { Proc *p; |
