make error handling in 9p service loops consistent

when we get eof, stop the loop immidiately and do not
rely on the read to eventually return an error.

when convM2S() fails to decode the message, error out
and stop the loop. there is no point in continuing.
This commit is contained in:
cinap_lenrek 2016-07-24 02:21:32 +02:00
parent a840b597ca
commit a0d4c5e208
28 changed files with 108 additions and 258 deletions

View file

@ -164,22 +164,11 @@ io(int srvfd)
pid = getpid();
fmtinstall('F', fcallfmt);
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads.
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error.
*/
n = read9pmsg(srvfd, mdata, sizeof mdata);
while((n = read9pmsg(srvfd, mdata, sizeof mdata)) != 0){
if(n < 0)
break;
if(n == 0)
continue;
if(convM2S(mdata, n, req) == 0)
continue;
panic(1, "mount read");
if(convM2S(mdata, n, req) != n)
panic(1, "convM2S format error");
if(chatty)
fprint(2, "9660srv %d:<-%F\n", pid, req);

View file

@ -40,13 +40,13 @@ xmesg(Session *s, int t)
}
again:
n = read9pmsg(s->fd, s->data, messagesize);
if(n == 0)
return -1;
if(n < 0){
clog("xmesg read error: %r\n");
return -1;
}
if(n == 0)
goto again;
if(convM2S(s->data, n, &s->f) <= 0){
if(convM2S(s->data, n, &s->f) != n){
clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n",
n, ((uchar*)s->data)[0], ((uchar*)s->data)[1],
((uchar*)s->data)[2], ((uchar*)s->data)[3]);

View file

@ -148,8 +148,7 @@ fsysproc(void *)
x = nil;
for(;;){
buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */
while((n = read9pmsg(sfd, buf, messagesize)) == 0 && !closing)
;
n = read9pmsg(sfd, buf, messagesize);
if(n <= 0){
if(closing)
break;

View file

@ -1038,14 +1038,11 @@ io(int in, int out)
/* after restart, let the system settle for 5 mins before warning */
lastwarning = time(0) - 24*60*60 + 5*60;
for(;;){
n = read9pmsg(in, mdata, messagesize);
if(n == 0)
continue;
while((n = read9pmsg(in, mdata, messagesize)) != 0){
if(n < 0)
error("mount read %d", n);
if(convM2S(mdata, n, &rhdr) == 0)
continue;
error("mount read: %r");
if(convM2S(mdata, n, &rhdr) != n)
error("convM2S format error: %r");
if(newkeys())
readusers();

View file

@ -49,7 +49,7 @@ watch(int fd)
sysfatal("out of memory");
while((n = read9pmsg(fd, buf, messagesize)) > 0){
if(convM2S(buf, n, &f) == 0){
if(convM2S(buf, n, &f) != n){
print("convM2S: %r\n");
continue;
}

View file

@ -681,18 +681,13 @@ fsrun(void *v)
}
free(d);
r = allocreq(fs, messagesize);
while((n = read9pmsg(fs->fd, r->buf, messagesize)) == 0)
;
n = read9pmsg(fs->fd, r->buf, messagesize);
if(n == 0)
threadexitsall("unmounted");
if(n < 0)
fatal("unmounted");
if(convM2S(r->buf, n, &r->f) == 0){
fprint(2, "can't convert %ux %ux %ux\n", r->buf[0],
r->buf[1], r->buf[2]);
free(r);
continue;
}
fatal("mount read: %r");
if(convM2S(r->buf, n, &r->f) != n)
fatal("convM2S format error: %r");
f = fsgetfid(fs, r->f.fid);
r->fid = f;

View file

@ -365,18 +365,14 @@ fsrun(void *a)
for(;;){
r = allocreq(messagesize);
qlock(&iolock);
while((n = read9pmsg(fs->fd, r->buf, messagesize)) == 0)
;
qunlock(&iolock);
n = read9pmsg(fs->fd, r->buf, messagesize);
if(n == 0)
threadexitsall("unmounted");
if(n < 0)
fatal("read9pmsg error: %r");
if(convM2S(r->buf, n, &r->f) == 0){
fprint(2, "can't convert %ux %ux %ux\n", r->buf[0],
r->buf[1], r->buf[2]);
free(r);
continue;
}
fatal("mount read: %r");
if(convM2S(r->buf, n, &r->f) != n)
fatal("convM2S format error: %r");
qunlock(&iolock);
f = fsgetfid(fs, r->f.fid);
r->fid = f;
@ -388,7 +384,6 @@ fsrun(void *a)
(*fcall[t])(fs, r, f);
fsputfid(fs, f);
}
}
/*

View file

@ -592,26 +592,12 @@ fsrun(Fs *fs, int fd)
int n;
buf = emalloc(messagesize);
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error
*/
n = read9pmsg(fd, buf, messagesize);
if(n == 0)
continue;
while((n = read9pmsg(fd, buf, messagesize)) != 0){
if(n < 0)
fatal("mount read");
fatal("mount read: %r");
rpc.data = (char*)buf + IOHDRSZ;
if(convM2S(buf, n, &rpc) == 0)
continue;
// fprint(2, "recv: %F\n", &rpc);
if(convM2S(buf, n, &rpc) != n)
fatal("convM2S format error: %r");
/*
* flushes are way too hard.

View file

@ -743,22 +743,11 @@ io(void)
pid = getpid();
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads.
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error.
*/
n = read9pmsg(mfd[0], mdata, messagesize);
while((n = read9pmsg(mfd[0], mdata, messagesize)) != 0){
if(n < 0)
error("mount read: %r");
if(n == 0)
continue;
if(convM2S(mdata, n, &thdr) == 0)
continue;
if(convM2S(mdata, n, &thdr) != n)
error("convM2S format error: %r");
if(debug)
fprint(2, "ramfs %d:<-%F\n", pid, &thdr);

View file

@ -808,14 +808,14 @@ rcvmsg(P9fs *p, Fcall *f)
char buf[128];
olen = p->len;
while((p->len = read9pmsg(p->fd[0], datarcv, sizeof(datarcv))) == 0)
;
p->len = read9pmsg(p->fd[0], datarcv, sizeof(datarcv));
if(p->len == 0)
exits("");
if(p->len < 0){
snprint(buf, sizeof buf, "read9pmsg(%d)->%ld: %r",
p->fd[0], p->len);
error(buf);
}
if((rlen = convM2S(datarcv, p->len, f)) != p->len)
error("rcvmsg format error, expected length %d, got %d",
rlen, p->len);

View file

@ -1028,14 +1028,7 @@ notefs(int fd)
ncpunote = 0;
for(;;){
n = read9pmsg(fd, buf, sizeof(buf));
if(n < 0){
if(dbg)
fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n);
break;
}
if(n == 0)
continue;
if(convM2S(buf, n, &f) <= BIT16SZ)
if(n <= 0 || convM2S(buf, n, &f) != n)
break;
if(dbg)
fprint(2, "notefs: ->%F\n", &f);

View file

@ -104,8 +104,9 @@ srvi(void *aux)
Msgbuf *mb, *ms;
uchar *b, *p, *e;
int n, m;
char buf[ERRMAX];
char err[ERRMAX];
err[0] = 0;
chan = aux;
srv = chan->pdata;
@ -116,13 +117,13 @@ srvi(void *aux)
e = b + mb->count;
Read:
while((n = read(srv->fd, p, e - p)) >= 0){
while((n = read(srv->fd, p, e - p)) > 0){
p += n;
while((p - b) >= BIT32SZ){
m = GBIT32(b);
if((m < BIT32SZ) || (m > mb->count)){
werrstr("bad length in 9P2000 message header");
goto Error;
strcpy(err, "bad length in 9P2000 message header");
goto Hangup;
}
if((n = (p - b) - m) < 0){
e = b + m;
@ -149,12 +150,11 @@ Read:
e = b + mb->count;
}
Error:
rerrstr(buf, sizeof(buf));
if(strstr(buf, "interrupt"))
goto Read;
if(n < 0)
errstr(err, sizeof(err));
chanhangup(chan, buf);
Hangup:
chanhangup(chan, err);
srvput(srv);
mbfree(mb);

View file

@ -135,22 +135,11 @@ io(int srvfd)
pid = getpid();
fmtinstall('F', fcallfmt);
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads.
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error.
*/
n = read9pmsg(srvfd, mdata, sizeof mdata);
while((n = read9pmsg(srvfd, mdata, sizeof mdata)) != 0){
if(n < 0)
break;
if(n == 0)
continue;
if(convM2S(mdata, n, req) == 0)
continue;
panic("mount read");
if(convM2S(mdata, n, req) != n)
panic("convM2S format error");
if(chatty)
fprint(2, "dossrv %d:<-%F\n", pid, req);

View file

@ -408,12 +408,11 @@ main(int argc, char **argv)
*/
for(;;) {
r = getsbuf();
while((n = read9pmsg(0, r->buf, messagesize)) == 0)
;
n = read9pmsg(0, r->buf, messagesize);
if(n <= 0)
fatal(nil);
Message:
if(convM2S(r->buf, n, &r->work) == 0)
if(convM2S(r->buf, n, &r->work) != n)
fatal("convM2S format error");
DEBUG(DFD, "%F\n", &r->work);

View file

@ -255,23 +255,19 @@ kaproc(void)
void
io(void)
{
char *err, buf[ERRMAX];
char *err;
int n;
kapid = kaproc();
while(!dying){
n = read9pmsg(mfd, mdata, messagesize);
if(n < 0){
errstr(buf, sizeof buf);
if(buf[0]=='\0' || strstr(buf, "hungup"))
exits("");
fatal("mount read: %s\n", buf);
}
if(n == 0)
continue;
if(convM2S(mdata, n, &thdr) == 0)
continue;
break;
if(n < 0)
fatal("mount read: %r");
if(convM2S(mdata, n, &thdr) != n)
fatal("convM2S format error: %r");
if(debug)
fprint(2, "<-%F\n", &thdr);/**/

View file

@ -526,22 +526,11 @@ io(void)
pid = getpid();
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads.
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error.
*/
n = read9pmsg(mfd[0], mdata, messagesize);
while((n = read9pmsg(mfd[0], mdata, messagesize)) != 0){
if(n < 0)
sysfatal("mount read");
if(n == 0)
continue;
if(convM2S(mdata, n, &thdr) == 0)
continue;
sysfatal("mount read: %r");
if(convM2S(mdata, n, &thdr) != n)
sysfatal("convM2S format error: %r");
if(debug)
fprint(2, "%s %d:<-%F\n", argv0, pid, &thdr);

View file

@ -321,14 +321,14 @@ mountinit(char *service, char *mntpt)
procsetname("%s", mntpt);
break;
case -1:
error("fork failed\n");
error("fork failed");
default:
/*
* put ourselves into the file system
*/
close(p[0]);
if(mount(p[1], -1, mntpt, MAFTER, "") < 0)
error("mount failed\n");
error("mount failed");
_exits(0);
}
mfd[0] = mfd[1] = p[0];
@ -447,13 +447,13 @@ io(void)
if(n < 0)
error("mount read");
if(n == 0)
continue;
break;
job = newjob();
if(convM2S(mdata, n, &job->request) != n){
syslog(1, logfile, "format error %ux %ux %ux %ux %ux",
mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
freejob(job);
continue;
break;
}
qlock(&dblock);
mf = newfid(job->request.fid);

View file

@ -812,14 +812,11 @@ io(int fd)
pid = getpid();
for(;;){
n = read9pmsg(fd, mdata, mesgsize);
while((n = read9pmsg(fd, mdata, mesgsize)) != 0){
if(n < 0)
sysfatal("mount read");
if(n == 0)
continue;
if(convM2S(mdata, n, &rhdr) == 0)
continue;
sysfatal("mount read: %r");
if(convM2S(mdata, n, &rhdr) != n)
sysfatal("convM2S format error: %r");
if(debug)
fprint(2, "paqfs %d:<-%F\n", pid, &rhdr);

View file

@ -237,10 +237,11 @@ fsysproc(void*)
if(buf == nil)
error("malloc failed: %r");
qlock(&readlock);
while((n = read9pmsg(srvfd, buf, messagesize)) == 0)
;
if(n < 0)
n = read9pmsg(srvfd, buf, messagesize);
if(n == 0)
threadexitsall("unmounted");
if(n < 0)
error("mount read: %r");
if(readlock.head == nil) /* no other processes waiting to read; start one */
proccreate(fsysproc, nil, Stack);
qunlock(&readlock);

View file

@ -56,16 +56,14 @@ io(void)
Fcall rhdr;
int n;
for(;;){
n = read9pmsg(srvfd, rbuf, sizeof rbuf-1);
if(n <= 0)
fatal("mount read");
if(convM2S(rbuf, n, &rhdr) == 0){
while((n = read9pmsg(srvfd, rbuf, sizeof rbuf-1)) != 0){
if(n < 0)
fatal("mount read: %r");
if(convM2S(rbuf, n, &rhdr) != n){
if(debugfd >= 0)
fprint(2, "%s: malformed message\n", argv0);
continue;
fatal("convM2S format error: %r");
}
if(debugfd >= 0)
fprint(debugfd, "<-%F\n", &rhdr);/**/
@ -94,9 +92,9 @@ reply(Fcall *r, char *error)
fprint(debugfd, "->%F\n", r);/**/
n = convS2M(r, rbuf, sizeof rbuf);
if(n == 0)
sysfatal("convS2M: %r");
fatal("convS2M: %r");
if(write(srvfd, rbuf, n) < 0)
sysfatal("reply: %r");
fatal("reply: %r");
}

View file

@ -195,9 +195,8 @@ filsysproc(void *arg)
buf = malloc(messagesize+UTFmax); /* UTFmax for appending partial rune in xfidwrite */
if(buf == nil)
error(Enomem);
while((n = read9pmsg(fs->sfd, buf, messagesize)) == 0)
yield();
if(n < 0){
n = read9pmsg(fs->sfd, buf, messagesize);
if(n <= 0){
yield(); /* if threadexitsall'ing, will not return */
fprint(2, "rio: %d: read9pmsg: %d %r\n", getpid(), n);
errorshouldabort = 0;

View file

@ -491,35 +491,15 @@ void
io(void)
{
char *err;
int n, nerr;
char buf[ERRMAX];
int n;
errstr(buf, sizeof buf);
for(nerr=0, buf[0]='\0'; nerr<100; nerr++){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error
*/
n = read9pmsg(mfd[0], mdata, sizeof mdata);
if(n==0)
continue;
if(n < 0){
if(buf[0]=='\0')
errstr(buf, sizeof buf);
continue;
}
nerr = 0;
buf[0] = '\0';
while((n = read9pmsg(mfd[0], mdata, sizeof mdata)) != 0){
if(n < 0)
error("mount read");
if(convM2S(mdata, n, &rhdr) != n)
error("convert error in convM2S");
if(verbose)
fprint(2, "tapefs: <=%F\n", &rhdr);/**/
thdr.data = (char*)mdata + IOHDRSZ;
thdr.stat = mdata + IOHDRSZ;
if(!fcalls[rhdr.type])
@ -542,10 +522,6 @@ io(void)
if(write(mfd[1], mdata, n) != n)
error("mount write");
}
if(buf[0]=='\0' || strstr(buf, "hungup"))
exits("");
fprint(2, "%s: mount read: %s\n", argv0, buf);
exits(buf);
}
int

View file

@ -914,18 +914,7 @@ io(void)
char *err;
int n;
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error
*/
n = read9pmsg(mfd[0], mdata, messagesize);
if(n == 0)
continue;
while((n = read9pmsg(mfd[0], mdata, messagesize)) != 0){
if(n < 0)
error("mount read");
if(convM2S(mdata, n, &thdr) != n)

View file

@ -704,12 +704,9 @@ io(void)
char *err;
int n;
for(;;){
n = read9pmsg(mfd[0], mdata, sizeof mdata);
while((n = read9pmsg(mfd[0], mdata, sizeof mdata)) != 0){
if(n < 0)
break;
if(n == 0)
continue;
sysfatal("mount read: %r");
if(convM2Su(mdata, n, &rhdr, dotu) != n)
sysfatal("convM2S conversion error");
@ -733,7 +730,7 @@ io(void)
fprint(2, "vacfs:->%F\n", &thdr);
n = convS2Mu(&thdr, mdata, messagesize, dotu);
if(n <= BIT16SZ)
sysfatal("convS2Mu conversion error");
sysfatal("convS2M conversion error");
if(err)
vtfree(err);

View file

@ -149,10 +149,9 @@ exportproc(Export *fs)
errdepth(ed);
q = smalloc(sizeof(Exq));
while((n = read9pmsg(fs->io, q->buf, Maxrpc)) == 0)
;
if(n < 0 || convM2S(q->buf, n, &q->rpc) != n)
goto bad;
n = read9pmsg(fs->io, q->buf, Maxrpc);
if(n <= 0 || convM2S(q->buf, n, &q->rpc) != n)
break;
if(exdebug)
print("export %d <- %F\n", getpid(), &q->rpc);
@ -181,7 +180,6 @@ exportproc(Export *fs)
kproc("exportfs", exslave, nil);
rendwakeup(&exq.rwait);
}
bad:
free(q);
if(exdebug)
fprint(2, "export proc shutting down: %r\n");

View file

@ -684,35 +684,25 @@ newfid(int fid)
void
io(void *)
{
char *err, e[32];
char *err;
int n;
extern int p[];
Fid *f;
threadsetname("file server");
close(p[1]);
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error
*/
n = read9pmsg(mfd[0], mdata, messagesize);
if(n == 0)
continue;
while((n = read9pmsg(mfd[0], mdata, messagesize)) != 0){
if(n < 0){
char e[32];
rerrstr(e, sizeof e);
if (strcmp(e, "interrupted") == 0){
if (debug & DbgFs) fprint(2, "read9pmsg interrupted\n");
continue;
}
return;
sysfatal("mount read: %s", e);
}
if(convM2S(mdata, n, &thdr) == 0)
continue;
if(convM2S(mdata, n, &thdr) != n)
sysfatal("convM2S format error: %r");
if(debug & DbgFs)
fprint(2, "io:<-%F\n", &thdr);

View file

@ -725,7 +725,6 @@ allocwork(Req *r)
void
srvio(void *arg)
{
char e[32];
int n;
Req *r;
Channel *dispatchc;
@ -734,34 +733,25 @@ srvio(void *arg)
dispatchc = arg;
r = reqalloc();
for(;;){
/*
* reading from a pipe or a network device
* will give an error after a few eof reads
* however, we cannot tell the difference
* between a zero-length read and an interrupt
* on the processes writing to us,
* so we wait for the error
*/
n = read9pmsg(srvfd[0], r->indata, messagesize);
if(n == 0)
continue;
while((n = read9pmsg(srvfd[0], r->indata, messagesize)) != 0){
if(n < 0){
char e[32];
rerrstr(e, sizeof e);
if (strcmp(e, "interrupted") == 0){
if (debug & DbgFs) fprint(2, "read9pmsg interrupted\n");
continue;
}
sysfatal("srvio: %s", e);
sysfatal("srvio: read: %s", e);
}
if(convM2S(r->indata, n, &r->ifcall) == 0)
continue;
if(convM2S(r->indata, n, &r->ifcall) != n)
sysfatal("srvio: convM2S: %r");
if(debug & DbgFs)
fprint(2, "io:<-%F\n", &r->ifcall);
sendp(dispatchc, r);
r = reqalloc();
}
threadexitsall(nil);
}
char *

View file

@ -59,9 +59,8 @@ getreq(Srv *s)
Req *r;
qlock(&s->rlock);
while((n = read9pmsg(s->infd, s->rbuf, s->msize)) == 0)
;
if(n < 0){
n = read9pmsg(s->infd, s->rbuf, s->msize);
if(n <= 0){
qunlock(&s->rlock);
return nil;
}