summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-04-28 09:12:04 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-04-28 09:12:04 +0200
commit1d42b2dac1a91534080c33f3f61ed7e60c7ea915 (patch)
treec1ebc10113251461c086c65e7cd09ae43b8bfc24 /sys
parente440d414d57af87e40fff560b58077443af91696 (diff)
avoid leaking up->dot into the closeproc
Diffstat (limited to 'sys')
-rw-r--r--sys/src/9/port/chan.c76
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);
}
/*