diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-01-30 06:26:03 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-01-30 06:26:03 +0100 |
commit | dbbbff89151794c838319e831254bcff6b3dbbcf (patch) | |
tree | 9efcb6002cfa8df32db861ab4c44f64b857efcd1 /sys/src/lib9p | |
parent | bc0e5ffa2293526ed3cf65a025263d2599c1f331 (diff) |
lib9p: defer closing down srv until the last request has been responded, Tversion message size
in multithreaded programs, we have to wait until all outstanding
requests have been responded before closing down the srv.
dont make write errors sysfatal(), only print them. in case if
listensrv() is used we dont want to exit the process in respond()
called by some worker thread.
make sure Tversion is only handled when there are no outstanding
requests and make sure message size is sane.
Diffstat (limited to 'sys/src/lib9p')
-rw-r--r-- | sys/src/lib9p/srv.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/sys/src/lib9p/srv.c b/sys/src/lib9p/srv.c index 33791cb18..12b1d7fe5 100644 --- a/sys/src/lib9p/srv.c +++ b/sys/src/lib9p/srv.c @@ -163,23 +163,34 @@ walkandclone(Req *r, char *(*walk1)(Fid*, char*, void*), char *(*clone)(Fid*, Fi } static void -sversion(Srv*, Req *r) +sversion(Srv *srv, Req *r) { + if(srv->rref.ref != 2){ + respond(r, Ebotch); + return; + } if(strncmp(r->ifcall.version, "9P", 2) != 0){ r->ofcall.version = "unknown"; respond(r, nil); return; } - r->ofcall.version = "9P2000"; - r->ofcall.msize = r->ifcall.msize; + if(r->ifcall.msize < 256){ + respond(r, "version: message size too small"); + return; + } + if(r->ifcall.msize < 1024*1024) + r->ofcall.msize = r->ifcall.msize; + else + r->ofcall.msize = 1024*1024; respond(r, nil); } + static void rversion(Req *r, char *error) { - assert(error == nil); - changemsize(r->srv, r->ofcall.msize); + if(error == nil) + changemsize(r->srv, r->ofcall.msize); } static void @@ -682,14 +693,18 @@ rwstat(Req*, char*) { } +static void srvclose(Srv *); + static void srvwork(void *v) { Srv *srv = v; Req *r; + incref(&srv->rref); incref(&srv->sref); while(r = getreq(srv)){ + incref(&srv->rref); if(r->error){ respond(r, r->error); continue; @@ -715,9 +730,19 @@ srvwork(void *v) } qunlock(&srv->slock); } - if(decref(&srv->sref)) + decref(&srv->sref); + srvclose(srv); +} + +static void +srvclose(Srv *srv) +{ + if(decref(&srv->rref)) return; + if(chatty9p) + fprint(2, "srvclose\n"); + free(srv->rbuf); srv->rbuf = nil; free(srv->wbuf); @@ -753,6 +778,9 @@ srv(Srv *srv) fmtinstall('D', dirfmt); fmtinstall('F', fcallfmt); + srv->sref.ref = 0; + srv->rref.ref = 0; + if(srv->fpool == nil) srv->fpool = allocfidpool(srv->destroyfid); if(srv->rpool == nil) @@ -819,7 +847,7 @@ if(chatty9p) qlock(&srv->wlock); n = convS2M(&r->ofcall, srv->wbuf, srv->msize); if(n <= 0){ - fprint(2, "n = %d %F\n", n, &r->ofcall); + fprint(2, "msize = %d n = %d %F\n", srv->msize, n, &r->ofcall); abort(); } assert(n > 2); @@ -827,7 +855,7 @@ if(chatty9p) closereq(removereq(r->pool, r->ifcall.tag)); m = write(srv->outfd, srv->wbuf, n); if(m != n) - sysfatal("lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); + fprint(2, "lib9p srv: write %d returned %d on fd %d: %r", n, m, srv->outfd); qunlock(&srv->wlock); qlock(&r->lk); /* no one will add flushes now */ @@ -844,6 +872,8 @@ if(chatty9p) closereq(r); else free(r); + + srvclose(srv); } void |