* 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(xprt, buf, len)
- register SVCXPRT *xprt;
- caddr_t buf;
- register int len;
+readtcp (register SVCXPRT *xprt, caddr_t buf, register int len)
{
- register int sock = xprt->xp_sock;
+ int sock = xprt->xp_sock;
#ifdef FD_SETSIZE
- fd_set mask;
- fd_set readfds;
-
- FD_ZERO(&mask);
- FD_SET(sock, &mask);
+ fd_set readfds;
#else
- register int mask = 1 << sock;
- int readfds;
+ int mask = 1 << sock;
+ int readfds;
#endif /* def FD_SETSIZE */
- do {
- struct timeval timeout = wait_per_try;
- readfds = mask;
- if (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL,
- &timeout) <= 0) {
- if (errno == EINTR) {
- continue;
- }
- goto fatal_err;
- }
+ while (1)
+ {
+ struct timeval timeout = wait_per_try;
+ readfds = svc_fdset;
#ifdef FD_SETSIZE
- } while (!FD_ISSET(sock, &readfds));
+ FD_SET (sock, &readfds);
#else
- } while (readfds != mask);
+ readfds = svc_fds;
+ readfds |= (1 << sock);
#endif /* def FD_SETSIZE */
- if ((len = read(sock, buf, len)) > 0) {
- return (len);
+ if (select (_rpc_dtablesize (), &readfds, (fd_set *) NULL,
+ (fd_set *) NULL, &timeout) <= 0)
+ {
+ if (errno == EINTR)
+ continue;
+ goto fatal_err;
}
+#ifdef FD_SETSIZE
+ if (FD_ISSET (sock, &readfds))
+#else
+ if (readfds != mask)
+#endif /* def FD_SETSIZE */
+ 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);
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ return -1;
}
/*