Commit Diff


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;
 	}