From: William A. Rowe Jr Date: Sat, 27 Jul 2002 18:13:59 +0000 (+0000) Subject: Refactor the ready_event so that it's scope is the absolute minimum X-Git-Tag: 2.0.40~98 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b475cd6438ced40cbd0799bd33985f74ec61a3e7;p=apache Refactor the ready_event so that it's scope is the absolute minimum necessary... we were leaking ready_event's. Close it in the parent and child the moment it is no longer needed. Also, fail more gracefully if the child process terminates before we ever receive the ready_event [should improve robustness significantly.] git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@96216 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c index 1ce1a275a8..05e0292677 100644 --- a/server/mpm/winnt/mpm_winnt.c +++ b/server/mpm/winnt/mpm_winnt.c @@ -119,7 +119,6 @@ static unsigned int g_blocked_threads = 0; static HANDLE shutdown_event; /* used to signal the parent to shutdown */ static HANDLE restart_event; /* used to signal the parent to restart */ -static HANDLE ready_event; /* used to signal the parent to duplicate sockets */ static HANDLE exit_event; /* used by parent to signal the child to exit */ static HANDLE max_requests_per_child_event; @@ -595,12 +594,17 @@ static APR_INLINE ap_listen_rec *find_ready_listener(fd_set * main_fds) } /* + * Passed the following handles [in sync with send_handles_to_child()] * + * ready event [signal the parent immediately, then close] + * exit event [save to poll later] + * scoreboard shm handle [to recreate the ap_scoreboard] */ void get_handles_from_parent(server_rec *s) { HANDLE pipe; HANDLE hScore; + HANDLE ready_event; DWORD BytesRead; void *sb_shared; apr_status_t rv; @@ -614,6 +618,9 @@ void get_handles_from_parent(server_rec *s) exit(APEXIT_CHILDINIT); } + SetEvent(ready_event); + CloseHandle(ready_event); + if (!ReadFile(pipe, &exit_event, sizeof(HANDLE), &BytesRead, (LPOVERLAPPED) NULL) || (BytesRead != sizeof(HANDLE))) { @@ -1576,6 +1583,11 @@ static int send_listeners_to_child(apr_pool_t *p, DWORD dwProcessId, return 0; } +enum waitlist_e { + waitlist_ready = 0, + waitlist_term = 1 +}; + static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_event, DWORD *child_pid) { @@ -1592,7 +1604,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ apr_file_t *child_err; apr_proc_t new_child; HANDLE hExitEvent; - HANDLE hReadyEvent; + HANDLE waitlist[2]; /* see waitlist_e */ char *cmd; char *cwd; @@ -1675,10 +1687,10 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ } /* Create the child_ready_event */ - hReadyEvent = CreateEvent (NULL, TRUE, FALSE, NULL); - if (!hReadyEvent) { - ap_log_error (APLOG_MARK, APLOG_CRIT, apr_get_os_error (), ap_server_conf, - "Parent: Could not create ready event for child process"); + waitlist[waitlist_ready] = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!waitlist[waitlist_ready]) { + ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, + "Parent: Could not create ready event for child process"); apr_pool_destroy (ptemp); return -1; } @@ -1689,6 +1701,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, "Parent: Could not create exit event for child process"); apr_pool_destroy(ptemp); + CloseHandle(waitlist[waitlist_ready]); return -1; } @@ -1714,6 +1727,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ "Parent: Failed to create the child process."); apr_pool_destroy(ptemp); CloseHandle(hExitEvent); + CloseHandle(waitlist[waitlist_ready]); CloseHandle(new_child.hproc); return -1; } @@ -1721,7 +1735,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Parent: Created child process %d", new_child.pid); - if (send_handles_to_child(ptemp, hReadyEvent, hExitEvent, + if (send_handles_to_child(ptemp, waitlist[waitlist_ready], hExitEvent, new_child.hproc, new_child.in)) { /* * This error is fatal, mop up the child and move on @@ -1731,6 +1745,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ SetEvent(hExitEvent); apr_pool_destroy(ptemp); CloseHandle(hExitEvent); + CloseHandle(waitlist[waitlist_ready]); CloseHandle(new_child.hproc); return -1; } @@ -1741,7 +1756,20 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_ * WSADuplicateSocket runs before the child process initializes * the listeners will be inherited anyway. */ - WaitForSingleObject (hReadyEvent, INFINITE); + waitlist[waitlist_term] = new_child.hproc; + rv = WaitForMultipleObjects(2, waitlist, FALSE, INFINITE); + if (rv != WAIT_OBJECT_0) { + /* + * Outch... that isn't a ready signal. It's dead, Jim! + */ + SetEvent(hExitEvent); + apr_pool_destroy(ptemp); + CloseHandle(hExitEvent); + CloseHandle(waitlist[waitlist_ready]); + CloseHandle(new_child.hproc); + return -1; + } + CloseHandle(waitlist[waitlist_ready]); if (send_listeners_to_child(ptemp, new_child.pid, new_child.in)) { /* @@ -2498,8 +2526,6 @@ static void winnt_child_init(apr_pool_t *pchild, struct server_rec *s) /* Set up events and the scoreboard */ get_handles_from_parent(s); - SetEvent (ready_event); - /* Set up the listeners */ get_listeners_from_parent(s);