summaryrefslogtreecommitdiff
path: root/sunrpc/svc_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sunrpc/svc_tcp.c')
-rw-r--r--sunrpc/svc_tcp.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index 41f95332e7..e162c02751 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -284,13 +284,19 @@ svctcp_destroy (SVCXPRT *xprt)
* All read operations timeout after 35 seconds.
* A timeout is fatal for the connection.
*/
-static struct timeval wait_per_try =
-{35, 0};
+static struct timeval wait_per_try = {35, 0};
/*
* reads data from the tcp connection.
* 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
readtcp (char *xprtptr, char *buf, int len)
@@ -298,39 +304,41 @@ readtcp (char *xprtptr, char *buf, int len)
SVCXPRT *xprt = (SVCXPRT *)xprtptr;
int sock = xprt->xp_sock;
#ifdef FD_SETSIZE
- fd_set mask;
fd_set readfds;
-
- FD_ZERO (&mask);
- FD_SET (sock, &mask);
#else
int mask = 1 << sock;
int readfds;
#endif /* def FD_SETSIZE */
- do
+ while (1)
{
struct timeval timeout = wait_per_try;
- readfds = mask;
+ readfds = svc_fdset;
+#ifdef FD_SETSIZE
+ FD_SET (sock, &readfds);
+#else
+ readfds |= (1 << sock);
+#endif /* def FD_SETSIZE */
if (select (_rpc_dtablesize (), &readfds, (fd_set *) NULL,
(fd_set *) NULL, &timeout) <= 0)
{
if (errno == EINTR)
- {
- continue;
- }
+ continue;
goto fatal_err;
}
+
#ifdef FD_SETSIZE
- }
- while (!FD_ISSET (sock, &readfds));
+ if (FD_ISSET (sock, &readfds))
#else
- }
- while (readfds != mask);
+ if (readfds == mask)
#endif /* def FD_SETSIZE */
- if ((len = read (sock, buf, len)) > 0)
- {
- return len;
+ break;
+
+ svc_getreqset (&readfds);
}
+
+ if ((len = read (sock, buf, len)) > 0)
+ return len;
+
fatal_err:
((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
return -1;