correct dangling pointer race (Bakul Shah)
diff --git a/src/libventi/conn.c b/src/libventi/conn.c index 5b6d543..e488c6d 100644 --- a/src/libventi/conn.c +++ b/src/libventi/conn.c
@@ -46,5 +46,6 @@ 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 index 3a1f6ea..bba6303 100644 --- a/src/libventi/queue.c +++ b/src/libventi/queue.c
@@ -12,6 +12,7 @@ struct Queue { + int ref; int hungup; QLock lk; Rendez r; @@ -26,14 +27,32 @@ 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 index 2807783..90ee140 100644 --- a/src/libventi/queue.h +++ b/src/libventi/queue.h
@@ -4,4 +4,5 @@ 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 index 7ada51a..70cc827 100644 --- a/src/libventi/send.c +++ b/src/libventi/send.c
@@ -147,7 +147,7 @@ _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 @@ _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 @@ vtrecv(VtConn *z) { Packet *p; + Queue *q; qlock(&z->lk); if(z->state != VtStateConnected){ @@ -197,8 +198,11 @@ 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 @@ int vtsend(VtConn *z, Packet *p) { + Queue *q; + qlock(&z->lk); if(z->state != VtStateConnected){ packetfree(p); @@ -221,11 +227,14 @@ 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; }