diff options
| author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-09-30 16:14:27 +0200 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-09-30 16:14:27 +0200 |
| commit | 5d64e428ebec115f9129a8f1de2f418e5418c8f4 (patch) | |
| tree | b72e28eacf495862f3eb2196633da00ffcf9c603 | |
| parent | fa08484d47b270a9c62310a3cd0124aef0cdd7d3 (diff) | |
| download | plan9front-5d64e428ebec115f9129a8f1de2f418e5418c8f4.tar.xz | |
fix devproc and killbig segment race
we have to acquire p->seglock before we lock the individual
segments of the process and lock them. if we dont then pexit()
might free the segments before we can lock them causing the
"qunlock called with qlock not held, from ..." prints.
| -rw-r--r-- | sys/src/9/port/devproc.c | 9 | ||||
| -rw-r--r-- | sys/src/9/port/proc.c | 6 |
2 files changed, 13 insertions, 2 deletions
diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c index 5f777d864..6fd600bcf 100644 --- a/sys/src/9/port/devproc.c +++ b/sys/src/9/port/devproc.c @@ -863,7 +863,13 @@ procread(Chan *c, void *va, long n, vlong off) l = TK2MS(l); readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } + l = 0; + eqlock(&p->seglock); + if(waserror()){ + qunlock(&p->seglock); + nexterror(); + } for(i=0; i<NSEG; i++){ if(s = p->seg[i]){ eqlock(&s->lk); @@ -871,6 +877,9 @@ procread(Chan *c, void *va, long n, vlong off) qunlock(&s->lk); } } + poperror(); + qunlock(&p->seglock); + readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l*BY2PG/1024, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 76aa3d0dd..a64ef4749 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -1494,7 +1494,7 @@ killbig(char *why) kp = 0; ep = procalloc.arena+conf.nproc; for(p = procalloc.arena; p < ep; p++) { - if(p->state == Dead || p->kp) + if(p->state == Dead || p->kp || !canqlock(&p->seglock)) continue; l = 0; for(i=1; i<NSEG; i++) { @@ -1504,12 +1504,13 @@ killbig(char *why) l += (ulong)mcountseg(s); qunlock(&s->lk); } + qunlock(&p->seglock); if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) { kp = p; max = l; } } - if(kp == 0) + if(kp == 0 || !canqlock(&kp->seglock)) return; print("%lud: %s killed: %s\n", kp->pid, kp->text, why); for(p = procalloc.arena; p < ep; p++) { @@ -1526,6 +1527,7 @@ killbig(char *why) qunlock(&s->lk); } } + qunlock(&kp->seglock); } /* |
