summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/svc_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/rpc/svc_unix.c')
-rw-r--r--lib/libc/rpc/svc_unix.c52
1 files changed, 35 insertions, 17 deletions
diff --git a/lib/libc/rpc/svc_unix.c b/lib/libc/rpc/svc_unix.c
index eb2e8f2..c44cc64 100644
--- a/lib/libc/rpc/svc_unix.c
+++ b/lib/libc/rpc/svc_unix.c
@@ -30,7 +30,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
-static char *rcsid = "$Id: svc_unix.c,v 1.2 1997/05/28 05:05:31 wpaul Exp $";
+static char *rcsid = "$Id: svc_unix.c,v 1.3 1998/05/15 22:53:47 wpaul Exp $";
#endif
/*
@@ -355,6 +355,13 @@ static struct timeval wait_per_try = { 35, 0 };
* reads data from the unix conection.
* any error is fatal and the connection is closed.
* (And a read of zero bytes is a half closed stream => error.)
+ *
+ * Note: we have to be careful here not to allow ourselves to become
+ * blocked too long in this routine. While we're waiting for data from one
+ * client, another client may be trying to connect. To avoid this situation,
+ * some code from svc_run() is transplanted here: the select() loop checks
+ * all RPC descriptors including the one we want and calls svc_getreqset2()
+ * to handle new requests if any are detected.
*/
static int
readunix(xprt, buf, len)
@@ -365,49 +372,60 @@ readunix(xprt, buf, len)
register int sock = xprt->xp_sock;
struct timeval start, delta, tv;
struct timeval tmp1, tmp2;
- fd_set *fds, readfds;
+ fd_set *fds;
+ extern fd_set *__svc_fdset;
+ extern int __svc_fdsetsize;
- if (sock + 1 > FD_SETSIZE) {
- int bytes = howmany(sock+1, NFDBITS) * sizeof(fd_mask);
+ delta = wait_per_try;
+ fds = NULL;
+ gettimeofday(&start, NULL);
+ do {
+ int bytes = howmany(__svc_fdsetsize, NFDBITS) *
+ sizeof(fd_mask);
+ if (fds != NULL)
+ free(fds);
fds = (fd_set *)malloc(bytes);
-
if (fds == NULL)
goto fatal_err;
- memset(fds, 0, bytes);
- } else {
- fds = &readfds;
- FD_ZERO(fds);
- }
+ memcpy(fds, __svc_fdset, bytes);
- delta = wait_per_try;
- gettimeofday(&start, NULL);
- do {
/* XXX we know the other bits are still clear */
FD_SET(sock, fds);
tv = delta; /* in case select() implements writeback */
- switch (select(sock + 1, fds, NULL, NULL, &tv)) {
+ switch (select(svc_maxfd + 1, fds, NULL, NULL, &tv)) {
case -1:
if (errno != EINTR)
goto fatal_err;
gettimeofday(&tmp1, NULL);
timersub(&tmp1, &start, &tmp2);
- timersub(&delta, &tmp2, &tmp1);
+ timersub(&wait_per_try, &tmp2, &tmp1);
if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
goto fatal_err;
delta = tmp1;
continue;
case 0:
goto fatal_err;
+ default:
+ if (!FD_ISSET(sock, fds)) {
+ svc_getreqset2(fds, svc_maxfd + 1);
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&wait_per_try, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ }
}
} while (!FD_ISSET(sock, fds));
if ((len = __msgread(sock, buf, len)) > 0) {
- if (fds != &readfds)
+ if (fds != NULL)
free(fds);
return (len);
}
fatal_err:
((struct unix_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
- if (fds != &readfds)
+ if (fds != NULL)
free(fds);
return (-1);
}
OpenPOWER on IntegriCloud