Fixed a race condition in close. The operation may not be dequeued by the second loop and the closing process may block forever in rendez. Notes: Thu Jul 15 13:45:31 EDT 2010 geoff We ultimately installed a later channel.c from Gorka. Reference: /n/sources/patch/applied/race-close Date: Tue May 11 17:59:14 CES 2010 Signed-off-by: paurea@lsub.org Reviewed-by: geoff --- /sys/src/libthread/channel.c Tue May 11 17:59:01 2010 +++ /sys/src/libthread/channel.c Tue May 11 17:58:58 2010 @@ -225,6 +225,8 @@ { Alt *a; int i, s, some; + char stags[16]; + char *q = stags; s = _procsplhi(); /* note handlers; see :/^alt */ lock(&chanlock); @@ -246,7 +248,7 @@ do{ some = 0; for(i = 0; i < c->nentry; i++){ - if((a = c->qentry[i]) == nil || *a->tag != nil) + if(q[i] != 0 || (a = c->qentry[i]) == nil || *a->tag != nil) continue; if(a->op != CHANSND && (a->op != CHANRCV || c->n != 0)) continue; @@ -255,6 +257,11 @@ _procsplx(s); while(_threadrendezvous(a->tag, Closed) == Intred) ; + if(i >= nelem(stags)){ /* should happen seldom */ + q = mallocz(c->nentry, 1); + memmove(q, stags, nelem(stags)); + } + q[i] = 1; s = _procsplhi(); lock(&chanlock); some++; @@ -266,6 +273,8 @@ _chanfree(c); unlock(&chanlock); _procsplx(s); + if(q != stags) + free(q); return 0; }