commit 4f6d2bb1e8e38aaeeeabb159272da19718bfb05d from: rsc date: Sun Apr 08 01:30:26 2007 UTC correct dangling pointer race (Bakul Shah) commit - 8ecb4ffe4c618bb484299a4a3b29f2a991903e53 commit + 4f6d2bb1e8e38aaeeeabb159272da19718bfb05d blob - 5b6d5436c41f99f1f681dd1701fccc2ea9303ea6 blob + e488c6db6a2c05803e56e1bbe114d4e8f751d25f --- src/libventi/conn.c +++ src/libventi/conn.c @@ -46,5 +46,6 @@ vtfreeconn(VtConn *z) packetfree(z->part); vtfree(z->version); vtfree(z->sid); + qunlock(&z->lk); vtfree(z); } blob - 3a1f6ea56d71bacf8dd503fe2ad6de5ebcb29972 blob + bba630324e0cd1d6cfd9f456cb6b347136b38295 --- src/libventi/queue.c +++ src/libventi/queue.c @@ -12,6 +12,7 @@ struct Qel struct Queue { + int ref; int hungup; QLock lk; Rendez r; @@ -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; blob - 2807783bddf7184c2426e36418c8f4156cf2bd2b blob + 90ee1402cc6527a31b6b439fa1e8a2ba43046ff8 --- src/libventi/queue.h +++ src/libventi/queue.h @@ -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*); blob - 7ada51af76155c6e1b84cf213292b75bd83e4ccc blob + 70cc8272770eae633b6297e45362de2fde73b597 --- src/libventi/send.c +++ src/libventi/send.c @@ -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); @@ -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); @@ -189,6 +189,7 @@ Packet* vtrecv(VtConn *z) { Packet *p; + Queue *q; qlock(&z->lk); if(z->state != VtStateConnected){ @@ -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); @@ -213,6 +217,8 @@ vtrecv(VtConn *z) int vtsend(VtConn *z, Packet *p) { + Queue *q; + qlock(&z->lk); if(z->state != VtStateConnected){ packetfree(p); @@ -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; }