tcorrect dangling pointer race (Bakul Shah) - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit 4f6d2bb1e8e38aaeeeabb159272da19718bfb05d
parent 8ecb4ffe4c618bb484299a4a3b29f2a991903e53
Author: rsc 
Date:   Sun,  8 Apr 2007 01:30:26 +0000

correct dangling pointer race (Bakul Shah)

Diffstat:
  M src/libventi/conn.c                 |       1 +
  M src/libventi/queue.c                |      21 ++++++++++++++++++++-
  M src/libventi/queue.h                |       3 ++-
  M src/libventi/send.c                 |      17 +++++++++++++----

4 files changed, 36 insertions(+), 6 deletions(-)
---
diff --git a/src/libventi/conn.c b/src/libventi/conn.c
t@@ -46,5 +46,6 @@ vtfreeconn(VtConn *z)
         packetfree(z->part);
         vtfree(z->version);
         vtfree(z->sid);
+        qunlock(&z->lk);
         vtfree(z);
 }
diff --git a/src/libventi/queue.c b/src/libventi/queue.c
t@@ -12,6 +12,7 @@ struct Qel
 
 struct Queue
 {
+        int ref;
         int hungup;
         QLock lk;
         Rendez r;
t@@ -26,14 +27,32 @@ _vtqalloc(void)
 
         q = vtmallocz(sizeof(Queue));
         q->r.l = &q->lk;
+        q->ref = 1;
+        return q;
+}
+
+Queue*
+_vtqincref(Queue *q)
+{
+        qlock(&q->lk);
+        q->ref++;
+        qunlock(&q->lk);
         return q;
 }
 
 void
-_vtqfree(Queue *q)
+_vtqdecref(Queue *q)
 {
         Qel *e;
         
+        qlock(&q->lk);
+        if(--q->ref > 0){
+                qunlock(&q->lk);
+                return;
+        }
+        assert(q->ref == 0);
+        qunlock(&q->lk);
+
         /* Leaks the pointers e->p! */
         while(q->head){
                 e = q->head;
diff --git a/src/libventi/queue.h b/src/libventi/queue.h
t@@ -4,4 +4,5 @@ int _vtqsend(Queue*, void*);
 void *_vtqrecv(Queue*);
 void _vtqhangup(Queue*);
 void *_vtnbqrecv(Queue*);
-void _vtqfree(Queue*);
+void _vtqdecref(Queue*);
+Queue *_vtqincref(Queue*);
diff --git a/src/libventi/send.c b/src/libventi/send.c
t@@ -147,7 +147,7 @@ vtrecvproc(void *v)
         _vtqhangup(q);
         while((p = _vtnbqrecv(q)) != nil)
                 packetfree(p);
-        _vtqfree(q);
+        _vtqdecref(q);
         z->readq = nil;
         rwakeup(&z->rpcfork);
         qunlock(&z->lk);
t@@ -178,7 +178,7 @@ vtsendproc(void *v)
         _vtqhangup(q);
         while((p = _vtnbqrecv(q)) != nil)
                 packetfree(p);
-        _vtqfree(q);
+        _vtqdecref(q);
         z->writeq = nil;
         rwakeup(&z->rpcfork);
         qunlock(&z->lk);
t@@ -189,6 +189,7 @@ Packet*
 vtrecv(VtConn *z)
 {
         Packet *p;
+        Queue *q;
 
         qlock(&z->lk);
         if(z->state != VtStateConnected){
t@@ -197,8 +198,11 @@ vtrecv(VtConn *z)
                 return nil;
         }
         if(z->readq){
+                q = _vtqincref(z->readq);
                 qunlock(&z->lk);
-                return _vtqrecv(z->readq);
+                p = _vtqrecv(q);
+                _vtqdecref(q);
+                return p;
         }
 
         qlock(&z->inlk);
t@@ -213,6 +217,8 @@ vtrecv(VtConn *z)
 int
 vtsend(VtConn *z, Packet *p)
 {
+        Queue *q;
+
         qlock(&z->lk);
         if(z->state != VtStateConnected){
                 packetfree(p);
t@@ -221,11 +227,14 @@ vtsend(VtConn *z, Packet *p)
                 return -1;
         }
         if(z->writeq){
+                q = _vtqincref(z->writeq);
                 qunlock(&z->lk);
-                if(_vtqsend(z->writeq, p) < 0){
+                if(_vtqsend(q, p) < 0){
+                        _vtqdecref(q);
                         packetfree(p);
                         return -1;
                 }
+                _vtqdecref(q);
                 return 0;
         }