bug in async select read
buganizer 1589219
channel is returning same values multiple times
R=r
OCL=23447
CL=23447
diff --git a/src/runtime/chan.c b/src/runtime/chan.c
index f6e2453..929d07f 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -5,6 +5,7 @@
#include "runtime.h"
static int32 debug = 0;
+static int32 xxx = 0;
static Lock chanlock;
typedef struct Hchan Hchan;
@@ -17,8 +18,9 @@
struct SudoG
{
G* g; // g and selgen constitute
- int16 offset; // offset of case number
int32 selgen; // a weak pointer to g
+ int16 offset; // offset of case number
+ int8 isfree; // offset of case number
SudoG* link;
byte elem[8]; // synch data element (+ more)
};
@@ -206,7 +208,6 @@
return;
asynch:
-//prints("\nasend\n");
while(c->qcount >= c->dataqsiz) {
if(pres != nil) {
unlock(&chanlock);
@@ -229,10 +230,8 @@
sg = dequeue(&c->recvq, c);
if(sg != nil) {
gp = sg->g;
- gp->param = sg;
freesg(c, sg);
unlock(&chanlock);
-//prints("wakeup\n");
ready(gp);
} else
unlock(&chanlock);
@@ -312,7 +311,6 @@
sg = dequeue(&c->sendq, c);
if(sg != nil) {
gp = sg->g;
- gp->param = sg;
freesg(c, sg);
unlock(&chanlock);
ready(gp);
@@ -411,7 +409,7 @@
if(debug) {
prints("newselect s=");
sys·printpointer(sel);
- prints("newselect size=");
+ prints(" size=");
sys·printint(size);
prints("\n");
}
@@ -451,7 +449,7 @@
c->elemalg->copy(c->elemsize, cas->u.elem, ae);
if(debug) {
- prints("newselect s=");
+ prints("selectsend s=");
sys·printpointer(sel);
prints(" pc=");
sys·printpointer(cas->pc);
@@ -495,7 +493,7 @@
cas->u.elemp = *(byte**)((byte*)&sel + eo);
if(debug) {
- prints("newselect s=");
+ prints("selectrecv s=");
sys·printpointer(sel);
prints(" pc=");
sys·printpointer(cas->pc);
@@ -510,7 +508,7 @@
}
-// selectrecv(sel *byte) (selected bool);
+// selectdefaul(sel *byte) (selected bool);
void
sys·selectdefault(Select *sel, ...)
{
@@ -534,7 +532,7 @@
cas->u.elemp = nil;
if(debug) {
- prints("newselect s=");
+ prints("selectdefault s=");
sys·printpointer(sel);
prints(" pc=");
sys·printpointer(cas->pc);
@@ -546,7 +544,6 @@
}
}
-uint32 xxx = 0;
// selectgo(sel *byte);
void
@@ -589,6 +586,7 @@
lock(&chanlock);
+loop:
// pass 1 - look for something already waiting
dfl = nil;
for(i=0; i<sel->ncase; i++) {
@@ -688,16 +686,25 @@
o -= sel->ncase;
}
+ g->param = nil;
g->status = Gwaiting;
unlock(&chanlock);
sys·Gosched();
lock(&chanlock);
sg = g->param;
+ if(sg == nil)
+ goto loop;
+
o = sg->offset;
cas = sel->scase[o];
c = cas->chan;
+ if(c->dataqsiz > 0) {
+// prints("shouldnt happen\n");
+ goto loop;
+ }
+
if(xxx) {
prints("wait-return: sel=");
sys·printpointer(sel);
@@ -712,12 +719,6 @@
prints("\n");
}
- if(c->dataqsiz > 0) {
- if(cas->send)
- goto asyns;
- goto asynr;
- }
-
if(!cas->send) {
if(cas->u.elemp != nil)
c->elemalg->copy(c->elemsize, cas->u.elemp, sg->elem);
@@ -734,7 +735,6 @@
sg = dequeue(&c->sendq, c);
if(sg != nil) {
gp = sg->g;
- gp->param = sg;
freesg(c, sg);
ready(gp);
}
@@ -748,7 +748,6 @@
sg = dequeue(&c->recvq, c);
if(sg != nil) {
gp = sg->g;
- gp->param = sg;
freesg(c, sg);
ready(gp);
}
@@ -849,6 +848,7 @@
sg->selgen = g->selgen;
sg->g = g;
sg->offset = 0;
+ sg->isfree = 0;
return sg;
}
@@ -856,6 +856,9 @@
static void
freesg(Hchan *c, SudoG *sg)
{
+ if(sg->isfree)
+ throw("chan.freesg: already free");
+ sg->isfree = 1;
sg->link = c->free;
c->free = sg;
}