@@ 188,6 188,7 @@ enum {
ConOpenAck,
ConOpenAckAck,
ConClose,
+ ConCloseAck,
ConReset,
};
@@ 442,7 443,7 @@ sdpopen(Chan* ch, int omode)
case Qstats:
case Qrstats:
c = sdp->conv[CONV(ch->qid)];
-print("open %d:%d: ref=%d\n", c->id, TYPE(ch->qid), c->ref);
+print("open %d:%ld: ref=%d\n", c->id, TYPE(ch->qid), c->ref);
qlock(c);
if(waserror()) {
qunlock(c);
@@ 717,7 718,7 @@ sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp)
switch(TYPE(c->qid)){
case Qtopdir:
case Qsdpdir:
- snprint(buf, sizeof(buf), "#E%d", c->dev);
+ snprint(buf, sizeof(buf), "#E%ld", c->dev);
devdir(c, (Qid){CHDIR|Qtopdir, 0}, buf, 0, eve, 0555, dp);
break;
case Qconvdir:
@@ 1199,6 1200,21 @@ conviput(Conv *c, Block *b, int control)
return nil;
}
+ switch(c->state) {
+ case CInit:
+ case CDial:
+ c->lstats.inBadOther++;
+ convoconnect(c, ConReset, c->dialid, c->acceptid);
+ convsetstate(c, CClosed);
+ break;
+ case CAccept:
+ case CRemoteClose:
+ case CLocalClose:
+ c->lstats.inBadOther++;
+ freeb(b);
+ return nil;
+ }
+
seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2];
b->rp += 3;
@@ 1328,6 1344,11 @@ conviconnect(Conv *c, int subtype, Block *b)
print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid);
+ if(subtype == ConReset) {
+ convsetstate(c, CClosed);
+ return;
+ }
+
switch(c->state) {
default:
panic("unknown state: %d", c->state);
@@ 1380,37 1401,29 @@ print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dial
convsetstate(c, COpen);
return;
case COpen:
+ case CLocalClose:
+ case CRemoteClose:
// duplicate that we ignore
return;
}
break;
case ConClose:
- convoconnect(c, ConReset, dialid, acceptid);
switch(c->state) {
- case CInit:
- case CDial:
- case CAccept:
- case CLocalClose:
- convsetstate(c, CClosed);
- return;
case COpen:
+ convoconnect(c, ConCloseAck, dialid, acceptid);
convsetstate(c, CRemoteClose);
return;
case CRemoteClose:
+ // duplicate ConClose
+ convoconnect(c, ConCloseAck, dialid, acceptid);
return;
}
break;
- case ConReset:
+ case ConCloseAck:
switch(c->state) {
- case CInit:
- case CDial:
- case CAccept:
- case COpen:
case CLocalClose:
convsetstate(c, CClosed);
return;
- case CRemoteClose:
- return;
}
break;
}
@@ 1418,6 1431,7 @@ Reset:
// invalid connection message - reset to sender
print("invalid conviconnect - sending reset\n");
convoconnect(c, ConReset, dialid, acceptid);
+ convsetstate(c, CClosed);
}
static void
@@ 1637,7 1651,7 @@ readcontrol(Conv *c, int n)
qlock(c); // this lock is not held during the sleep below
for(;;) {
- if(c->state == CInit || c->state == CClosed) {
+ if(c->chan == nil || c->state == CClosed) {
qunlock(c);
print("readcontrol: return error - state = %s\n", convstatename[c->state]);
error("conversation closed");
@@ 10,28 10,22 @@
*/
int
-newfd(Chan *c)
+growfd(Fgrp *f, int fd) /* fd is always >= 0 */
{
- int i;
- Fgrp *f = up->fgrp;
Chan **newfd, **oldfd;
- lock(f);
- for(i=0; i<f->nfd; i++)
- if(f->fd[i] == 0){
- if(i > f->maxfd)
- f->maxfd = i;
- f->fd[i] = c;
- unlock(f);
- return i;
- }
+ if(fd < f->nfd)
+ return 0;
+ if(fd >= f->nfd+DELTAFD)
+ return -1; /* out of range */
+ if(fd % 100 == 0)
+ pprint("warning: process exceeds %d file descriptors\n", fd);
/*
* Unbounded allocation is unwise; besides, there are only 16 bits
* of fid in 9P
*/
if(f->nfd >= 5000){
- Exhausted:
- unlock(f);
+ Exhausted:
exhausted("file descriptors");
return -1;
}
@@ 41,14 35,33 @@ newfd(Chan *c)
oldfd = f->fd;
memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
f->fd = newfd;
+ free(oldfd);
f->nfd += DELTAFD;
- f->maxfd = i;
- f->fd[i] = c;
+ if(fd > f->maxfd)
+ f->maxfd = fd;
+ return 1;
+}
+
+int
+newfd(Chan *c)
+{
+ int fd;
+ Fgrp *f;
+
+ f = up->fgrp;
+ lock(f);
+ for(fd=0; fd<f->nfd; fd++)
+ if(f->fd[fd] == 0)
+ break;
+ if(fd >= f->nfd && growfd(f, fd) < 0){
+ unlock(f);
+ return -1;
+ }
+ if(fd > f->maxfd)
+ f->maxfd = fd;
+ f->fd[fd] = c;
unlock(f);
- free(oldfd);
- if(i%100 == 0)
- pprint("warning: process exceeds %d file descriptors\n", i);
- return i;
+ return fd;
}
Chan*
@@ 155,6 168,8 @@ syspipe(ulong *arg)
c[1] = d->open(c[1], ORDWR);
fd[0] = newfd(c[0]);
fd[1] = newfd(c[1]);
+ if(fd[0] < 0 || fd[1] < 0)
+ error(Enofd);
((long*)arg[0])[0] = fd[0];
((long*)arg[0])[1] = fd[1];
poperror();
@@ 175,7 190,7 @@ sysdup(ulong *arg)
fd = arg[1];
if(fd != -1){
lock(f);
- if(fd<0 || f->nfd<=fd) {
+ if(fd<0 || growfd(f, fd)<0) {
unlock(f);
cclose(c);
error(Ebadfd);
@@ 194,6 209,8 @@ sysdup(ulong *arg)
nexterror();
}
fd = newfd(c);
+ if(fd < 0)
+ error(Enofd);
poperror();
}
@@ 215,6 232,8 @@ sysopen(ulong *arg)
validaddr(arg[0], 1, 0);
c = namec((char*)arg[0], Aopen, arg[1], 0);
fd = newfd(c);
+ if(fd < 0)
+ error(Enofd);
poperror();
return fd;
}
@@ 724,6 743,8 @@ syscreate(ulong *arg)
validaddr(arg[0], 1, 0);
c = namec((char*)arg[0], Acreate, arg[1], arg[2]);
fd = newfd(c);
+ if(fd < 0)
+ error(Enofd);
poperror();
return fd;
}