Hi,

Here is the proposed patch for WIN32 that will like
epoll favor the APR_POLLHUP pollset_poll events when the
socket has been closed.
It uses additional WSAEVENT event record that is
created if APR_POOLHUP or APR_POOLPRI is specified
as reqevent.

Application that polls the accepted socket will
not need to read the data from the socket in case
it has been half-closed (like with epoll) to determine
if the APR_POLLIN is a real POLLIN or socket closed.

Any comments?

Regards,
Mladen.
Index: network_io/win32/sockopt.c
===================================================================
--- network_io/win32/sockopt.c  (revision 409392)
+++ network_io/win32/sockopt.c  (working copy)
@@ -24,6 +24,13 @@
 {
     u_long zero = 0;
 
+    /* Unregister any winsock event.
+     * To set socket back to blocking mode, it is first necessary
+     * to clear the event record associated with socket via a call
+     * to WSAEventSelect with lNetworkEvents set to zero, in which case
+     * the hEventObject parameter will be ignored.
+     */
+    WSAEventSelect(sd, NULL, 0);
     if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
         return apr_get_netos_error();
     }
Index: network_io/win32/sockets.c
===================================================================
--- network_io/win32/sockets.c  (revision 409392)
+++ network_io/win32/sockets.c  (working copy)
@@ -42,6 +42,12 @@
         thesocket->overlapped = NULL;
     }
 #endif
+#if !defined(CYGWIN)
+    if (thesocket->event) {
+        WSACloseEvent(thesocket->event);
+        thesocket->event = NULL;   
+    }
+#endif
     return APR_SUCCESS;
 }
 
Index: include/arch/win32/apr_arch_networkio.h
===================================================================
--- include/arch/win32/apr_arch_networkio.h     (revision 409392)
+++ include/arch/win32/apr_arch_networkio.h     (working copy)
@@ -53,7 +53,9 @@
     sock_userdata_t    *userdata;
 
     /* if there is a timeout set, then this pollset is used */
-    apr_pollset_t *pollset;
+    apr_pollset_t      *pollset;
+    /* socket event handle */
+    WSAEVENT            event;
 };
 
 #ifdef _WIN32_WCE
Index: poll/unix/select.c
===================================================================
--- poll/unix/select.c  (revision 409392)
+++ poll/unix/select.c  (working copy)
@@ -268,6 +268,24 @@
         return APR_EBADF;
     }
 #endif
+
+#if defined(WIN32) && !defined(CYGWIN)
+    if (!descriptor->desc.s->event &&
+        (descriptor->reqevents & (APR_POLLHUP | APR_POLLPRI))) {
+        descriptor->desc.s->event = WSACreateEvent();
+        if (descriptor->desc.s->event) {
+            long events = 0;
+            if (descriptor->reqevents & APR_POLLHUP)
+                events |= FD_CLOSE;
+            if (descriptor->reqevents & APR_POLLPRI)
+                events |= FD_OOB;
+            WSAEventSelect(fd, descriptor->desc.s->event, events);
+        }
+        else
+            return apr_get_netos_error();
+    }
+#endif
+
     if (descriptor->reqevents & APR_POLLIN) {
         FD_SET(fd, &(pollset->readset));
     }
@@ -396,6 +414,20 @@
             if (FD_ISSET(fd, &exceptset)) {
                 pollset->result_set[j].rtnevents |= APR_POLLERR;
             }
+#if defined(WIN32) && !defined(CYGWIN)
+            /* Check for winsock network events */
+            if (pollset->query_set[i].desc.s->event) {
+                WSANETWORKEVENTS events;
+                if (WSAEnumNetworkEvents(fd,
+                    pollset->query_set[i].desc.s->event,
+                    &events) == 0) {
+                    if (events.lNetworkEvents & FD_CLOSE)
+                        pollset->result_set[j].rtnevents |= APR_POLLHUP;
+                    if (events.lNetworkEvents & FD_OOB)
+                        pollset->result_set[j].rtnevents |= APR_POLLPRI;
+                }
+            }
+#endif       
             j++;
         }
     }

Reply via email to