summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-01-30 06:26:03 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2013-01-30 06:26:03 +0100
commitdbbbff89151794c838319e831254bcff6b3dbbcf (patch)
tree9efcb6002cfa8df32db861ab4c44f64b857efcd1
parentbc0e5ffa2293526ed3cf65a025263d2599c1f331 (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.
-rw-r--r--sys/include/9p.h1
-rw-r--r--sys/src/lib9p/srv.c46
2 files changed, 39 insertions, 8 deletions
diff --git a/sys/include/9p.h b/sys/include/9p.h
index a8fb1fdc1..27bec9b9a 100644
--- a/sys/include/9p.h
+++ b/sys/include/9p.h
@@ -234,6 +234,7 @@ struct Srv {
QLock slock;
Ref sref;
+ Ref rref;
};
void srv(Srv*);
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