correct dangling pointer race (Bakul Shah)
This commit is contained in:
parent
8ecb4ffe4c
commit
4f6d2bb1e8
4 changed files with 36 additions and 6 deletions
|
|
@ -46,5 +46,6 @@ vtfreeconn(VtConn *z)
|
|||
packetfree(z->part);
|
||||
vtfree(z->version);
|
||||
vtfree(z->sid);
|
||||
qunlock(&z->lk);
|
||||
vtfree(z);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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*);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue