Consider this piece of code, where essentially a server poll() on its socket,
waiting for any client connections, then on any event received from poll,
test for errors (eg. the server socket has been closed),
and THEN do an accept() to get the client's connected socket:
...
/* Here we wait indefinitely... */
ret = apr_poll(poll, &n, -1);
if (ret != APR_SUCCESS) return NULL;
ret = apr_poll_revents_get(&event, sock_srvr, poll);
if (ret != APR_SUCCESS) return NULL;
/* Verify if there was any error */
if (event & (APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
apr_socket_close(sock_srvr);
return NULL;
}
/* Ok there was a connection from a client */
ret = apr_accept(&sock_client, sock_srvr, context);
if (ret != APR_SUCCESS) return NULL;
...
This will work on UNIX (I have tested it on SunOS 5.6, HPUX 11.00, AIX 4.2 and
AIX 5.1)
but it fails on WIN32.
The reason is that in apr_poll_revents_get() function, WSARecv() returns error
10057,
which is WSAENOTCONN, which means: "The socket is not connected.".
I trap this returned error code to make an additional test to see if there is
indeed an error.
Here is the diff :
----------------------------------------------------------------------------------
--- apr/network_io/win32/poll.c Wed Mar 13 15:39:25 2002
+++ apr_new/network_io/win32/poll.c Mon Jun 3 18:23:30 2002
@@ -177,6 +177,22 @@
revents |= APR_POLLHUP;
break;
}
+ case WSAENOTCONN: {
+ /* Maybe the socket is created and listening, but not
connected,
+ * so everything is fine.
+ */
+ BOOL rep;
+ int sz_rep = sizeof(rep);
+
+ if (getsockopt(sock->sock, SOL_SOCKET, SO_ACCEPTCONN,
&rep, &sz_rep) != SOCKET_ERROR) {
+ if (rep) {
+ break; /* no error */
+ }
+ }
+ revents ^= APR_POLLIN;
+ revents |= APR_POLLERR;
+ break;
+ }
case WSAENOTSOCK: {
revents ^= APR_POLLIN;
revents |= APR_POLLNVAL;
----------------------------------------------------------------------------------
Jean-Francois BRIERE