ref: 1af7a1aced139ad7c90a053241e46f2ea2aaa2b4
parent: f0874a14c3685a08e98c3fcb1ebd81514b1e3ded
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jun 17 21:59:59 EDT 2024
mq: avoid double-advancing messages
--- a/mq.c
+++ b/mq.c
@@ -370,12 +370,12 @@
void
mqread(Req *r)
{
- char *p, *e, *b;
+ char *p, *e, *b, *d;
+ int n, mcount;
Aux *a;
Msg *m;
Rd *rd;
Mq *q;
- int n;
if(QTYPE(r->fid->qid.path) == Qroot){
dirread9p(r, rootgen, r->fid->aux);
@@ -396,35 +396,40 @@
/* queued messages: pop data off */
rd = &q->rd[a->id];
- m = rd->hd;
- p = emalloc(r->ifcall.count);
- e = p + r->ifcall.count;
+ d = emalloc(r->ifcall.count);
+ p = d;
+ e = d + r->ifcall.count;
r->ofcall.data = p;
- while(1){
- assert(rd->off >= 0 && rd->off < m->count);
+ while(rd->hd != nil && p != e){
+ m = rd->hd;
b = m->data + rd->off;
- if(e - p >= m->count - rd->off){
+ n = e - p;
+ mcount = m->count;
+ assert(rd->off >= 0 && rd->off <= m->count);
+ incref(m);
+ if(n >= m->count - rd->off){
n = m->count - rd->off;
+ memcpy(p, b, n);
rd->hd = m->next;
rd->off = 0;
if(rd->hd == nil)
rd->tl = nil;
- if(decref(m) == 0)
- free(m);
+ decref(m);
}else{
- n = e - p;
- rd->off += (e - p);
+ memcpy(p, b, n);
+ rd->off += n;
}
- memcpy(p, b, n);
p += n;
- rd->hd = m->next;
- m = rd->hd;
- if(!coalesce || m == nil || e - p < m->count)
+ if(decref(m) == 0)
+ free(m);
+ if(!coalesce || n < mcount)
break;
}
- r->ofcall.count = p - r->ofcall.data;
+ assert(r->ofcall.count <= r->ifcall.count);
+ r->ofcall.count = p - d;
respond(r, nil);
+ free(d);
}
void