You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2009/03/05 20:50:43 UTC
svn commit: r750567 - /httpd/httpd/trunk/server/mpm/winnt/child.c
Author: wrowe
Date: Thu Mar 5 19:50:41 2009
New Revision: 750567
URL: http://svn.apache.org/viewvc?rev=750567&view=rev
Log:
Use a single event for the lifetime of the 'AcceptFilter none' variety
sockets; it appears that resetting the accept event while another was
waiting would break the pending connection, causing host socket resets.
Modified:
httpd/httpd/trunk/server/mpm/winnt/child.c
Modified: httpd/httpd/trunk/server/mpm/winnt/child.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/mpm/winnt/child.c?rev=750567&r1=750566&r2=750567&view=diff
==============================================================================
--- httpd/httpd/trunk/server/mpm/winnt/child.c (original)
+++ httpd/httpd/trunk/server/mpm/winnt/child.c Thu Mar 5 19:50:41 2009
@@ -270,6 +270,7 @@
SOCKADDR_STORAGE ss_listen;
int namelen = sizeof(ss_listen);
#endif
+ u_long zero = 0;
core_sconf = ap_get_module_config(ap_server_conf->module_config,
&core_module);
@@ -283,7 +284,8 @@
accf = 0;
else {
accf = 0;
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(),
+ accf_name = "none";
+ ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(),
ap_server_conf,
"winnt_accept: unrecognized AcceptFilter '%s', "
"only 'data', 'connect' or 'none' are valid. "
@@ -302,15 +304,54 @@
}
#endif
- ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
- "Child %d: Starting thread to listen on port %d.",
- my_pid, lr->bind_addr->port);
+ if (accf > 0) /* 'data' or 'connect' */
+ {
+ /* first, high priority event is an already accepted connection */
+ events[1] = exit_event;
+ events[2] = max_requests_per_child_event;
+ }
+ else /* accf == 0, 'none' */
+ {
+reinit: /* target of data or connect upon too many AcceptEx failures */
+
+ /* last, low priority event is a not yet accepted connection */
+ events[0] = exit_event;
+ events[1] = max_requests_per_child_event;
+ events[2] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ /* The event needs to be removed from the accepted socket,
+ * if not removed from the listen socket prior to accept(),
+ */
+ rv = WSAEventSelect(nlsd, events[2], FD_ACCEPT);
+ if (rv) {
+ ap_log_error(APLOG_MARK, APLOG_ERR,
+ apr_get_netos_error(), ap_server_conf,
+ "WSAEventSelect() failed.");
+ CloseHandle(events[2]);
+ return 1;
+ }
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
+ "Child %d: Accept thread listening on %s:%d using %s", my_pid,
+ lr->bind_addr->hostname ? lr->bind_addr->hostname : "*",
+ lr->bind_addr->port, accf_name);
+
while (!shutdown_in_progress) {
if (!context) {
context = mpm_get_completion_context();
if (!context) {
+ /* Hopefully a temporary condition in the provider? */
+ ++err_count;
+ if (err_count > MAX_ACCEPTEX_ERR_COUNT) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
+ "winnt_accept: Too many failures grabbing a "
+ "connection ctx. Aborting.");
+ break;
+ }
+
/* Temporary resource constraint? */
- ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(),
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, apr_get_netos_error(),
ap_server_conf,
"winnt_accept: Failed to grab a connection ctx."
" Temporary resource constraint? Retrying.");
@@ -351,7 +392,6 @@
continue;
}
-
if (accf == 2) { /* 'data' */
len = APR_BUCKET_BUFF_SIZE;
buf = apr_bucket_alloc(len, context->ba); /* XXX: check for failure? */
@@ -428,16 +468,18 @@
"'AcceptFilter none'.");
err_count = 0;
accf = 0;
+ goto reinit;
}
continue;
}
err_count = 0;
events[0] = context->overlapped.hEvent;
- events[1] = exit_event;
- events[2] = max_requests_per_child_event;
- rv = WaitForMultipleObjects(3, events, FALSE, INFINITE);
+ do {
+ rv = WaitForMultipleObjectsEx(3, events, FALSE, INFINITE, TRUE);
+ } while (rv == WAIT_IO_COMPLETION);
+
if (rv == WAIT_OBJECT_0) {
if ((context->accept_socket != INVALID_SOCKET) &&
!GetOverlappedResult((HANDLE)context->accept_socket,
@@ -506,15 +548,8 @@
else /* (accf = 0) e.g. 'none' */
{
/* There is no socket reuse without AcceptEx() */
- if (context->accept_socket != INVALID_SOCKET) {
+ if (context->accept_socket != INVALID_SOCKET)
closesocket(context->accept_socket);
- context->accept_socket = INVALID_SOCKET;
- }
-
- err_count = 0;
- events[0] = exit_event;
- events[1] = max_requests_per_child_event;
- events[2] = context->overlapped.hEvent;
/* This could be a persistant event per-listener rather than
* per-accept. However, the event needs to be removed from
@@ -522,25 +557,11 @@
* prior to accept(), or the event select is inherited.
* and must be removed from the accepted socket.
*/
- rv = WSAEventSelect(nlsd, events[2], FD_ACCEPT);
- if (rv) {
- rv = apr_get_netos_error();
- if (rv == APR_FROM_OS_ERROR(WSAEINPROGRESS)) {
- ap_log_error(APLOG_MARK, APLOG_WARNING,
- rv, ap_server_conf,
- "WSAEventSelect() failed, retrying.");
- continue;
- }
- /* A more serious error that 'retry', log it */
- ap_log_error(APLOG_MARK, APLOG_WARNING,
- rv, ap_server_conf,
- "WSAEventSelect() failed.");
- break;
- }
+ do {
+ rv = WaitForMultipleObjectsEx(3, events, FALSE, INFINITE, TRUE);
+ } while (rv == WAIT_IO_COMPLETION);
- rv = WaitForMultipleObjects(3, events, FALSE, INFINITE);
- WSAEventSelect(nlsd, events[2], 0);
if (rv != WAIT_OBJECT_0 + 2) {
/* not FD_ACCEPT;
@@ -588,7 +609,19 @@
}
break;
}
+ /* Per MSDN, cancel the inherited association of this socket
+ * to the WSAEventSelect API, and restore the state corresponding
+ * to apr_os_sock_make's default assumptions (really, a flaw within
+ * os_sock_make and os_sock_put that it does not query).
+ */
+ WSAEventSelect(context->accept_socket, 0, 0);
+ ioctlsocket(context->accept_socket, FIONBIO, &zero);
+ setsockopt(context->accept_socket, SOL_SOCKET, SO_RCVTIMEO,
+ (char *) &zero, sizeof(zero));
+ setsockopt(context->accept_socket, SOL_SOCKET, SO_SNDTIMEO,
+ (char *) &zero, sizeof(zero));
context->overlapped.Pointer = NULL;
+ err_count = 0;
}
sockinfo.os_sock = &context->accept_socket;
@@ -606,10 +639,14 @@
&context->overlapped);
context = NULL;
}
+ if (!accf)
+ CloseHandle(events[2]);
+
if (!shutdown_in_progress) {
/* Yow, hit an irrecoverable error! Tell the child to die. */
SetEvent(exit_event);
}
+
ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf,
"Child %d: Accept thread exiting.", my_pid);
return 0;