From 3a19470202c5c0f6e9375e5d57535c3d508f2edf Mon Sep 17 00:00:00 2001 From: rsc Date: Sat, 4 Nov 2006 18:46:00 +0000 Subject: In non-blocking recv functions in libmux and libdraw, distinguish between "cannot receive without blocking" and "EOF on connection". In libmux, do not elect async guys muxers, so that synchronous RPC calls run in the main event loop (e.g., in eresized) do not get stuck. Fixes problem reported by Lu Xuxiao, namely that jpg etc. would spin at 100% cpu usage. --- src/libdraw/drawclient.c | 34 ++++++++++++++++++++-------------- src/libdraw/event.c | 12 +++++++++++- 2 files changed, 31 insertions(+), 15 deletions(-) (limited to 'src/libdraw') diff --git a/src/libdraw/drawclient.c b/src/libdraw/drawclient.c index 62615942..93c56235 100644 --- a/src/libdraw/drawclient.c +++ b/src/libdraw/drawclient.c @@ -13,7 +13,7 @@ int chattydrawclient; static int drawgettag(Mux *mux, void *vmsg); static void* drawrecv(Mux *mux); -static void* drawnbrecv(Mux *mux); +static int drawnbrecv(Mux *mux, void**); static int drawsend(Mux *mux, void *vmsg); static int drawsettag(Mux *mux, void *vmsg, uint tag); static int canreadfd(int); @@ -83,40 +83,46 @@ drawsend(Mux *mux, void *vmsg) return write(d->srvfd, msg, n); } -static void* -_drawrecv(Mux *mux, int nb) +static int +_drawrecv(Mux *mux, int canblock, void **vp) { int n; uchar buf[4], *p; Display *d; d = mux->aux; - if(nb && !canreadfd(d->srvfd)) - return nil; + *vp = nil; + if(!canblock && !canreadfd(d->srvfd)) + return 0; if((n=readn(d->srvfd, buf, 4)) != 4) - return nil; + return 1; GET(buf, n); p = malloc(n); if(p == nil){ fprint(2, "out of memory allocating %d in drawrecv\n", n); - return nil; + return 1; } memmove(p, buf, 4); - if(readn(d->srvfd, p+4, n-4) != n-4) - return nil; - return p; + if(readn(d->srvfd, p+4, n-4) != n-4){ + free(p); + return 1; + } + *vp = p; + return 1; } static void* drawrecv(Mux *mux) { - return _drawrecv(mux, 0); + void *p; + _drawrecv(mux, 1, &p); + return p; } -static void* -drawnbrecv(Mux *mux) +static int +drawnbrecv(Mux *mux, void **vp) { - return _drawrecv(mux, 1); + return _drawrecv(mux, 0, vp); } static int diff --git a/src/libdraw/event.c b/src/libdraw/event.c index 1da3fb39..101aa374 100644 --- a/src/libdraw/event.c +++ b/src/libdraw/event.c @@ -214,10 +214,14 @@ static int finishrpc(Muxrpc *r, Wsysmsg *w) { uchar *p; + void *v; int n; - if((p = muxrpccanfinish(r)) == nil) + if(!muxrpccanfinish(r, &v)) return 0; + p = v; + if(p == nil) /* eof on connection */ + exit(0); GET(p, n); convM2W(p, n, w); free(p); @@ -269,6 +273,9 @@ extract(int canblock) if(eslave[i].rpc == nil) eslave[i].rpc = startrpc(Trdmouse); if(eslave[i].rpc){ + /* if ready, don't block in select */ + if(eslave[i].rpc->p) + canblock = 0; FD_SET(display->srvfd, &rset); FD_SET(display->srvfd, &xset); if(display->srvfd > max) @@ -278,6 +285,9 @@ extract(int canblock) if(eslave[i].rpc == nil) eslave[i].rpc = startrpc(Trdkbd); if(eslave[i].rpc){ + /* if ready, don't block in select */ + if(eslave[i].rpc->p) + canblock = 0; FD_SET(display->srvfd, &rset); FD_SET(display->srvfd, &xset); if(display->srvfd > max) -- cgit v1.2.3