Loading server/mpm/winnt/mpm_winnt.c +46 −33 Changes for server/mpm/winnt/mpm_winnt.c: 46 added lines, 33 removed lines. Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ AP_DECLARE(void) mpm_recycle_completion_context(PCOMP_CONTEXT context) if (context) { apr_pool_clear(context->ptrans); context->next = NULL; ResetEvent(context->Overlapped.hEvent); apr_thread_mutex_lock(qlock); if (qtail) qtail->next = context; Loading Loading @@ -261,7 +262,7 @@ AP_DECLARE(PCOMP_CONTEXT) mpm_get_completion_context(void) */ context = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT)); context->Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); context->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (context->Overlapped.hEvent == NULL) { /* Hopefully this is a temporary condition ... */ ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_os_error(), ap_server_conf, Loading Loading @@ -926,25 +927,23 @@ static PCOMP_CONTEXT win9x_get_connection(PCOMP_CONTEXT context) static void winnt_accept(void *listen_socket) { apr_os_sock_info_t sockinfo; PCOMP_CONTEXT context; PCOMP_CONTEXT context = NULL; DWORD BytesRead; SOCKET nlsd; int lasterror; int rv; nlsd = (SOCKET) listen_socket; while (!shutdown_in_progress) { if (!context) { context = mpm_get_completion_context(); if (!context) { /* Hopefully whatever is preventing us from getting a * completion context is a temporary resource constraint. * Yield the rest of our time slice. */ /* Temporary resource constraint? */ Sleep(0); continue; } } again: /* Create and initialize the accept socket */ if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); Loading @@ -954,7 +953,7 @@ static void winnt_accept(void *listen_socket) "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); goto again; continue; } } Loading @@ -968,41 +967,53 @@ static void winnt_accept(void *listen_socket) PADDED_ADDR_SIZE, &BytesRead, &context->Overlapped)) { lasterror = apr_get_netos_error(); if (lasterror == APR_FROM_OS_ERROR(WSAEINVAL)) { rv = apr_get_netos_error(); if (rv == APR_FROM_OS_ERROR(WSAEINVAL)) { /* Hack alert. Occasionally, TransmitFile will not recycle the * accept socket (usually when the client disconnects early). * Get a new socket and try the call again. */ closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; ap_log_error(APLOG_MARK, APLOG_DEBUG, lasterror, ap_server_conf, ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, "winnt_accept: AcceptEx failed due to early client " "disconnect. Reallocate the accept socket and try again."); if (shutdown_in_progress) break; else goto again; continue; } else if (lasterror != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { ap_log_error(APLOG_MARK,APLOG_ERR, lasterror, ap_server_conf, else if (rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf, "winnt_accept: AcceptEx failed. Attempting to recover."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; Sleep(100); goto again; continue; } /* Wait for pending i/o */ WaitForSingleObject(context->Overlapped.hEvent, INFINITE); /* Wait for pending i/o. Wake up once per second to check for shutdown */ while (1) { rv = WaitForSingleObject(context->Overlapped.hEvent, 1000); if (rv == WAIT_OBJECT_0) { if (!GetOverlappedResult(context->Overlapped.hEvent, &context->Overlapped, &BytesRead, FALSE)) { ap_log_error(APLOG_MARK,APLOG_WARNING, GetLastError(), ap_server_conf, "winnt_accept: Asynchronous AcceptEx failed."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; } /* ### There is a race condition here. The mainline may hit * WSATerminate before this thread reawakens. Look First. */ break; } /* WAIT_TIMEOUT */ if (shutdown_in_progress) { closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; break; } } if (context->accept_socket == INVALID_SOCKET) { continue; } } /* Inherit the listen socket settings. Required for * shutdown() to work Loading Loading @@ -1038,12 +1049,14 @@ static void winnt_accept(void *listen_socket) */ PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED, &context->Overlapped); context = NULL; } 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); } static PCOMP_CONTEXT winnt_get_connection(PCOMP_CONTEXT context) { Loading Loading @@ -1099,6 +1112,8 @@ static void worker_main(long thread_num) PCOMP_CONTEXT context = NULL; ap_sb_handle_t *sbh; ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, "Child %d: Worker thread %d starting.", my_pid, thread_num); while (1) { conn_rec *c; apr_int32_t disconnected; Loading Loading @@ -1147,8 +1162,8 @@ static void worker_main(long thread_num) ap_update_child_status_from_indexes(0, thread_num, SERVER_DEAD, (request_rec *) NULL); ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf, "Child %d: Thread exiting.", my_pid); ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, "Child %d: Worker thread %d exiting.", my_pid, thread_num); } static void cleanup_thread(thread *handles, int *thread_cnt, int thread_to_clean) Loading Loading @@ -1357,17 +1372,15 @@ static void child_main() */ shutdown_in_progress = 1; /* Tell the worker threads they may exit when done handling * a connection. */ workers_may_exit = 1; /* Close the listening sockets. */ for (lr = ap_listeners; lr ; lr = lr->next) { apr_socket_close(lr->sd); } Sleep(1000); /* Tell the worker threads to exit */ workers_may_exit = 1; /* Release the start_mutex to let the new process (in the restart * scenario) a chance to begin accepting and servicing requests */ Loading Loading
server/mpm/winnt/mpm_winnt.c +46 −33 Changes for server/mpm/winnt/mpm_winnt.c: 46 added lines, 33 removed lines. Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ AP_DECLARE(void) mpm_recycle_completion_context(PCOMP_CONTEXT context) if (context) { apr_pool_clear(context->ptrans); context->next = NULL; ResetEvent(context->Overlapped.hEvent); apr_thread_mutex_lock(qlock); if (qtail) qtail->next = context; Loading Loading @@ -261,7 +262,7 @@ AP_DECLARE(PCOMP_CONTEXT) mpm_get_completion_context(void) */ context = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT)); context->Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); context->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (context->Overlapped.hEvent == NULL) { /* Hopefully this is a temporary condition ... */ ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_os_error(), ap_server_conf, Loading Loading @@ -926,25 +927,23 @@ static PCOMP_CONTEXT win9x_get_connection(PCOMP_CONTEXT context) static void winnt_accept(void *listen_socket) { apr_os_sock_info_t sockinfo; PCOMP_CONTEXT context; PCOMP_CONTEXT context = NULL; DWORD BytesRead; SOCKET nlsd; int lasterror; int rv; nlsd = (SOCKET) listen_socket; while (!shutdown_in_progress) { if (!context) { context = mpm_get_completion_context(); if (!context) { /* Hopefully whatever is preventing us from getting a * completion context is a temporary resource constraint. * Yield the rest of our time slice. */ /* Temporary resource constraint? */ Sleep(0); continue; } } again: /* Create and initialize the accept socket */ if (context->accept_socket == INVALID_SOCKET) { context->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); Loading @@ -954,7 +953,7 @@ static void winnt_accept(void *listen_socket) "winnt_accept: Failed to allocate an accept socket. " "Temporary resource constraint? Try again."); Sleep(100); goto again; continue; } } Loading @@ -968,41 +967,53 @@ static void winnt_accept(void *listen_socket) PADDED_ADDR_SIZE, &BytesRead, &context->Overlapped)) { lasterror = apr_get_netos_error(); if (lasterror == APR_FROM_OS_ERROR(WSAEINVAL)) { rv = apr_get_netos_error(); if (rv == APR_FROM_OS_ERROR(WSAEINVAL)) { /* Hack alert. Occasionally, TransmitFile will not recycle the * accept socket (usually when the client disconnects early). * Get a new socket and try the call again. */ closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; ap_log_error(APLOG_MARK, APLOG_DEBUG, lasterror, ap_server_conf, ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, ap_server_conf, "winnt_accept: AcceptEx failed due to early client " "disconnect. Reallocate the accept socket and try again."); if (shutdown_in_progress) break; else goto again; continue; } else if (lasterror != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { ap_log_error(APLOG_MARK,APLOG_ERR, lasterror, ap_server_conf, else if (rv != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf, "winnt_accept: AcceptEx failed. Attempting to recover."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; Sleep(100); goto again; continue; } /* Wait for pending i/o */ WaitForSingleObject(context->Overlapped.hEvent, INFINITE); /* Wait for pending i/o. Wake up once per second to check for shutdown */ while (1) { rv = WaitForSingleObject(context->Overlapped.hEvent, 1000); if (rv == WAIT_OBJECT_0) { if (!GetOverlappedResult(context->Overlapped.hEvent, &context->Overlapped, &BytesRead, FALSE)) { ap_log_error(APLOG_MARK,APLOG_WARNING, GetLastError(), ap_server_conf, "winnt_accept: Asynchronous AcceptEx failed."); closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; } /* ### There is a race condition here. The mainline may hit * WSATerminate before this thread reawakens. Look First. */ break; } /* WAIT_TIMEOUT */ if (shutdown_in_progress) { closesocket(context->accept_socket); context->accept_socket = INVALID_SOCKET; break; } } if (context->accept_socket == INVALID_SOCKET) { continue; } } /* Inherit the listen socket settings. Required for * shutdown() to work Loading Loading @@ -1038,12 +1049,14 @@ static void winnt_accept(void *listen_socket) */ PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED, &context->Overlapped); context = NULL; } 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); } static PCOMP_CONTEXT winnt_get_connection(PCOMP_CONTEXT context) { Loading Loading @@ -1099,6 +1112,8 @@ static void worker_main(long thread_num) PCOMP_CONTEXT context = NULL; ap_sb_handle_t *sbh; ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, "Child %d: Worker thread %d starting.", my_pid, thread_num); while (1) { conn_rec *c; apr_int32_t disconnected; Loading Loading @@ -1147,8 +1162,8 @@ static void worker_main(long thread_num) ap_update_child_status_from_indexes(0, thread_num, SERVER_DEAD, (request_rec *) NULL); ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf, "Child %d: Thread exiting.", my_pid); ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ap_server_conf, "Child %d: Worker thread %d exiting.", my_pid, thread_num); } static void cleanup_thread(thread *handles, int *thread_cnt, int thread_to_clean) Loading Loading @@ -1357,17 +1372,15 @@ static void child_main() */ shutdown_in_progress = 1; /* Tell the worker threads they may exit when done handling * a connection. */ workers_may_exit = 1; /* Close the listening sockets. */ for (lr = ap_listeners; lr ; lr = lr->next) { apr_socket_close(lr->sd); } Sleep(1000); /* Tell the worker threads to exit */ workers_may_exit = 1; /* Release the start_mutex to let the new process (in the restart * scenario) a chance to begin accepting and servicing requests */ Loading