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++;
}
}