diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-04-28 09:12:04 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-04-28 09:12:04 +0200 |
commit | 1d42b2dac1a91534080c33f3f61ed7e60c7ea915 (patch) | |
tree | c1ebc10113251461c086c65e7cd09ae43b8bfc24 /sys | |
parent | e440d414d57af87e40fff560b58077443af91696 (diff) |
avoid leaking up->dot into the closeproc
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/9/port/chan.c | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/sys/src/9/port/chan.c b/sys/src/9/port/chan.c index 203f5bcba..61c0dc2e3 100644 --- a/sys/src/9/port/chan.c +++ b/sys/src/9/port/chan.c @@ -520,54 +520,64 @@ closeproc(void*) } static void -closechan(Chan *c, int sync) +closechanq(Chan *c) +{ + lock(&clunkq.l); + clunkq.nqueued++; + c->next = nil; + if(clunkq.head) + clunkq.tail->next = c; + else + clunkq.head = c; + clunkq.tail = c; + unlock(&clunkq.l); + + if(canqlock(&clunkq.q)){ + c = up->dot; + up->dot = nil; + kproc("closeproc", closeproc, nil); + up->dot = c; + }else + wakeup(&clunkq.r); +} + +void +cclose(Chan *c) { if(c == nil || c->ref < 1 || c->flag&CFREE) - panic("closechan %#p", getcallerpc(&c)); + panic("cclose %#p", getcallerpc(&c)); - DBG("closechan %p name=%s ref=%ld\n", c, chanpath(c), c->ref); + DBG("cclose %p name=%s ref=%ld\n", c, chanpath(c), c->ref); if(decref(c)) return; + if(devtab[c->type]->dc == L'M') if((c->flag&(CRCLOSE|CCACHE)) == CCACHE) - if((c->qid.type&(QTEXCL|QTMOUNT|QTAUTH)) == 0) - sync = 0; - - if(sync){ - if(!waserror()){ - devtab[c->type]->close(c); - poperror(); - } - chanfree(c); - } else { - lock(&clunkq.l); - clunkq.nqueued++; - c->next = nil; - if(clunkq.head) - clunkq.tail->next = c; - else - clunkq.head = c; - clunkq.tail = c; - unlock(&clunkq.l); - - if(canqlock(&clunkq.q)) - kproc("closeproc", closeproc, nil); - else - wakeup(&clunkq.r); + if((c->qid.type&(QTEXCL|QTMOUNT|QTAUTH)) == 0){ + closechanq(c); + return; } -} -void -cclose(Chan *c) -{ - closechan(c, 1); + if(!waserror()){ + devtab[c->type]->close(c); + poperror(); + } + chanfree(c); } void ccloseq(Chan *c) { - closechan(c, 0); + if(c == nil || c->ref < 1 || c->flag&CFREE) + panic("ccloseq %#p", getcallerpc(&c)); + + DBG("ccloseq %p name=%s ref=%ld\n", c, chanpath(c), c->ref); + + if(decref(c)) + return; + + closechanq(c); } /* |