tcorrect dangling pointer race (Bakul Shah) - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 4f6d2bb1e8e38aaeeeabb159272da19718bfb05d
 (DIR) parent 8ecb4ffe4c618bb484299a4a3b29f2a991903e53
 (HTM) Author: rsc <devnull@localhost>
       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(-)
       ---
 (DIR) 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);
        }
 (DIR) 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;
 (DIR) 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*);
 (DIR) 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;
                }