From: Stephen D. <sd...@gm...> - 2006-07-13 21:50:10
|
The nssock driver does this: case DriverRecv: timeout.sec = sock->driver->recvwait; n = Ns_SockRecvBufs(sock->sock, bufs, nbufs, &timeout); break; case DriverSend: timeout.sec = sock->driver->sendwait; n = Ns_SockSendBufs(sock->sock, bufs, nbufs, &timeout); break; ...which is called by the driver thread to read the request, headers etc. It's a non-blocking socket, so why the timeout? Ns_SockRecvBufs looks like this: n = SockRecv(sock, bufs, nbufs); if (n < 0 && ns_sockerrno == EWOULDBLOCK && Ns_SockTimedWait(sock, NS_SOCK_READ, timeoutPtr) == NS_OK) { n = SockRecv(sock, bufs, nbufs); } return n; i.e. if on the first attempt to read from the socket the kernel returns EWOULDBLOCK, wait for 30 seconds for something to arrive. Sockets only return EWOULDBLOCK if they are in non-blocking mode, and there is nothing to read/write. It's in non-blocking mode because we want to multiplex all sockets efficiently in the driver thread. Ns_SockTimedWait calls poll() with a timeout. It doesn't return until data arrives or the timeout expires. So, this can block the driver thread for up to 30 seconds. Does this make any sense? It's hard to see how this would be triggered in practice. We only attempt to read from the socket if the poll loop indicates the socket is readable. However, the Linux man page for select() (which also applies to poll) does say: Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circum-stances. Thus it may be safer to use O_NONBLOCK on sockets that should not block. We do use O_NONBLOCK, but then defeat that with an extra 30 second poll() timeout... |