From: Graham Leggett Date: Sat, 16 Nov 2013 19:24:53 +0000 (+0000) Subject: mpm_unix: Add ap_mpm_podx_* implementation to avoid code duplication X-Git-Tag: 2.4.7~18 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e9eef7a853855546d56cc8759f44f0696a83f7ba;p=apache mpm_unix: Add ap_mpm_podx_* implementation to avoid code duplication and align w/ trunk. trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1409214 http://svn.apache.org/viewvc?view=revision&revision=1410004 2.4.x patch: http://people.apache.org/~jim/patches/httpd-2.4-podx-v2.patch Submitted by: jim Reviewed by: rjung, minfrin git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1542557 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index e294c4f895..7c9aab9683 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.4.7 + *) mpm_unix: Add ap_mpm_podx_* implementation to avoid code duplication + and align w/ trunk. [Jim Jagielski] + *) Fix potential rejection of valid MaxMemFree and ThreadStackSize directives. [Mike Rumph ] diff --git a/STATUS b/STATUS index ce3824ac84..91c3f4978f 100644 --- a/STATUS +++ b/STATUS @@ -97,12 +97,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mpm_unix: Add ap_mpm_podx_* implementation to avoid code duplication - and align w/ trunk. - trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1409214 - http://svn.apache.org/viewvc?view=revision&revision=1410004 - 2.4.x patch: http://people.apache.org/~jim/patches/httpd-2.4-podx-v2.patch - +1: jim, rjung, minfrin PATCHES PROPOSED TO BACKPORT FROM TRUNK: diff --git a/include/ap_mmn.h b/include/ap_mmn.h index b3dbeeccec..965483f0ea 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -421,6 +421,7 @@ * 20120211.24 (2.4.7-dev) add open_htaccess hook. * 20120211.25 (2.4.7-dev) Add conn_sense_e * 20120211.26 (2.4.7-dev) Add util_fcgi.h, FastCGI protocol support + * 20120211.27 (2.4.7-dev) Add ap_podx_restart_t and ap_mpm_podx_* */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -428,7 +429,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 26 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 27 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/mpm_common.h b/include/mpm_common.h index 0a98d7009e..8bb0ec5452 100644 --- a/include/mpm_common.h +++ b/include/mpm_common.h @@ -278,6 +278,50 @@ AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod); */ AP_DECLARE(void) ap_mpm_pod_killpg(ap_pod_t *pod, int num); +#define AP_MPM_PODX_RESTART_CHAR '$' +#define AP_MPM_PODX_GRACEFUL_CHAR '!' + +typedef enum { AP_MPM_PODX_NORESTART, AP_MPM_PODX_RESTART, AP_MPM_PODX_GRACEFUL } ap_podx_restart_t; + +/** + * Open the extended pipe-of-death. + * @param p The pool to use for allocating the pipe + * @param pod The pipe-of-death that is created. + */ +AP_DECLARE(apr_status_t) ap_mpm_podx_open(apr_pool_t *p, ap_pod_t **pod); + +/** + * Check the extended pipe to determine if the process has been signalled to die. + */ +AP_DECLARE(int) ap_mpm_podx_check(ap_pod_t *pod); + +/** + * Close the pipe-of-death + * + * @param pod The pipe-of-death to close. + */ +AP_DECLARE(apr_status_t) ap_mpm_podx_close(ap_pod_t *pod); + +/** + * Write data to the extended pipe-of-death, signalling that one child process + * should die. + * @param pod the pipe-of-death to write to. + * @param graceful restart-type + */ +AP_DECLARE(apr_status_t) ap_mpm_podx_signal(ap_pod_t *pod, + ap_podx_restart_t graceful); + +/** + * Write data to the extended pipe-of-death, signalling that all child process + * should die. + * @param pod The pipe-of-death to write to. + * @param num The number of child processes to kill + * @param graceful restart-type + */ +AP_DECLARE(void) ap_mpm_podx_killpg(ap_pod_t *pod, int num, + ap_podx_restart_t graceful); + + #endif /* !WIN32 || DOXYGEN */ /** diff --git a/server/mpm/event/config3.m4 b/server/mpm/event/config3.m4 index e7ec6320ca..8aa1631fab 100644 --- a/server/mpm/event/config3.m4 +++ b/server/mpm/event/config3.m4 @@ -2,6 +2,6 @@ dnl ## XXX - Need a more thorough check of the proper flags to use APACHE_SUBST(MOD_MPM_EVENT_LDADD) -APACHE_MPM_MODULE(event, $enable_mpm_event, event.lo fdqueue.lo pod.lo,[ +APACHE_MPM_MODULE(event, $enable_mpm_event, event.lo fdqueue.lo,[ AC_CHECK_FUNCS(pthread_kill) ], , [\$(MOD_MPM_EVENT_LDADD)]) diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index 1f89c5e335..77a64ac29e 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -84,7 +84,6 @@ #include "http_core.h" /* for get_remote_host */ #include "http_connection.h" #include "ap_mpm.h" -#include "pod.h" #include "mpm_common.h" #include "ap_listen.h" #include "scoreboard.h" @@ -321,7 +320,7 @@ static event_retained_data *retained; #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t) -static ap_event_pod_t *pod; +static ap_pod_t *pod; /* The event MPM respects a couple of runtime flags that can aid * in debugging. Setting the -DNO_DETACH flag will prevent the root process @@ -2199,25 +2198,25 @@ static void child_main(int child_num_arg) apr_signal(SIGTERM, dummy_signal_handler); /* Watch for any messages from the parent over the POD */ while (1) { - rv = ap_event_pod_check(pod); - if (rv == AP_NORESTART) { + rv = ap_mpm_podx_check(pod); + if (rv == AP_MPM_PODX_NORESTART) { /* see if termination was triggered while we slept */ switch (terminate_mode) { case ST_GRACEFUL: - rv = AP_GRACEFUL; + rv = AP_MPM_PODX_GRACEFUL; break; case ST_UNGRACEFUL: - rv = AP_RESTART; + rv = AP_MPM_PODX_RESTART; break; } } - if (rv == AP_GRACEFUL || rv == AP_RESTART) { + if (rv == AP_MPM_PODX_GRACEFUL || rv == AP_MPM_PODX_RESTART) { /* make sure the start thread has finished; * signal_threads() and join_workers depend on that */ join_start_thread(start_thread_id); signal_threads(rv == - AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL); + AP_MPM_PODX_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL); break; } } @@ -2446,7 +2445,7 @@ static void perform_idle_server_maintenance(void) if (idle_thread_count > max_spare_threads) { /* Kill off one child */ - ap_event_pod_signal(pod, TRUE); + ap_mpm_podx_signal(pod, AP_MPM_PODX_GRACEFUL); retained->idle_spawn_rate = 1; } else if (idle_thread_count < min_spare_threads) { @@ -2677,7 +2676,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) /* Time to shut down: * Kill child processes, tell them to call child_exit, etc... */ - ap_event_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_RESTART); ap_reclaim_child_processes(1, /* Start with SIGTERM */ event_note_child_killed); @@ -2698,7 +2697,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) /* Close our listeners, and then ask our children to do same */ ap_close_listeners(); - ap_event_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_GRACEFUL); ap_relieve_child_processes(event_note_child_killed); if (!child_fatal) { @@ -2738,7 +2737,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) * way, try and make sure that all of our processes are * really dead. */ - ap_event_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_RESTART); ap_reclaim_child_processes(1, event_note_child_killed); return DONE; @@ -2764,7 +2763,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) AP_SIG_GRACEFUL_STRING " received. Doing graceful restart"); /* wake up the children...time to die. But we'll have more soon */ - ap_event_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_GRACEFUL); /* This is mostly for debugging... so that we know what is still @@ -2777,7 +2776,7 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s) * and a SIGHUP, we may as well use the same signal, because some user * pthreads are stealing signals from us left and right. */ - ap_event_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_RESTART); ap_reclaim_child_processes(1, /* Start with SIGTERM */ event_note_child_killed); @@ -2814,7 +2813,7 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t * plog, } if (!one_process) { - if ((rv = ap_event_pod_open(pconf, &pod))) { + if ((rv = ap_mpm_podx_open(pconf, &pod))) { ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv, (startup ? NULL : s), "could not open pipe-of-death"); diff --git a/server/mpm/event/pod.c b/server/mpm/event/pod.c deleted file mode 100644 index 5deed8baa9..0000000000 --- a/server/mpm/event/pod.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "pod.h" - -#include "apr_portable.h" - -#if APR_HAVE_UNISTD_H -#include -#endif - -APLOG_USE_MODULE(mpm_event); - -AP_DECLARE(apr_status_t) ap_event_pod_open(apr_pool_t * p, ap_event_pod_t ** pod) -{ - apr_status_t rv; - - *pod = apr_palloc(p, sizeof(**pod)); - rv = apr_file_pipe_create(&((*pod)->pod_in), &((*pod)->pod_out), p); - if (rv != APR_SUCCESS) { - return rv; - } -/* - apr_file_pipe_timeout_set((*pod)->pod_in, 0); -*/ - (*pod)->p = p; - - /* close these before exec. */ - apr_file_inherit_unset((*pod)->pod_in); - apr_file_inherit_unset((*pod)->pod_out); - - return APR_SUCCESS; -} - -AP_DECLARE(int) ap_event_pod_check(ap_event_pod_t * pod) -{ - char c; - apr_os_file_t fd; - int rc; - - /* we need to surface EINTR so we'll have to grab the - * native file descriptor and do the OS read() ourselves - */ - apr_os_file_get(&fd, pod->pod_in); - rc = read(fd, &c, 1); - if (rc == 1) { - switch (c) { - case RESTART_CHAR: - return AP_RESTART; - case GRACEFUL_CHAR: - return AP_GRACEFUL; - } - } - return AP_NORESTART; -} - -AP_DECLARE(apr_status_t) ap_event_pod_close(ap_event_pod_t * pod) -{ - apr_status_t rv; - - rv = apr_file_close(pod->pod_out); - if (rv != APR_SUCCESS) { - return rv; - } - - rv = apr_file_close(pod->pod_in); - if (rv != APR_SUCCESS) { - return rv; - } - return rv; -} - -static apr_status_t pod_signal_internal(ap_event_pod_t * pod, int graceful) -{ - apr_status_t rv; - char char_of_death = graceful ? GRACEFUL_CHAR : RESTART_CHAR; - apr_size_t one = 1; - - rv = apr_file_write(pod->pod_out, &char_of_death, &one); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00522) - "write pipe_of_death"); - } - return rv; -} - -AP_DECLARE(apr_status_t) ap_event_pod_signal(ap_event_pod_t * pod, int graceful) -{ - return pod_signal_internal(pod, graceful); -} - -AP_DECLARE(void) ap_event_pod_killpg(ap_event_pod_t * pod, int num, int graceful) -{ - int i; - apr_status_t rv = APR_SUCCESS; - - for (i = 0; i < num && rv == APR_SUCCESS; i++) { - rv = pod_signal_internal(pod, graceful); - } -} diff --git a/server/mpm/event/pod.h b/server/mpm/event/pod.h deleted file mode 100644 index 861e4d9957..0000000000 --- a/server/mpm/event/pod.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file event/pod.h - * @brief pod definitions - * - * @addtogroup APACHE_MPM_EVENT - * @{ - */ - -#include "apr.h" -#include "apr_strings.h" -#define APR_WANT_STRFUNC -#include "apr_want.h" - -#include "httpd.h" -#include "http_config.h" -#include "http_log.h" -#include "http_main.h" -#include "mpm_common.h" -#include "ap_mpm.h" -#include "ap_listen.h" -#include "mpm_default.h" - -#define RESTART_CHAR '$' -#define GRACEFUL_CHAR '!' - -#define AP_RESTART 0 -#define AP_GRACEFUL 1 - -typedef struct ap_event_pod_t ap_event_pod_t; - -struct ap_event_pod_t -{ - apr_file_t *pod_in; - apr_file_t *pod_out; - apr_pool_t *p; -}; - -AP_DECLARE(apr_status_t) ap_event_pod_open(apr_pool_t * p, ap_event_pod_t ** pod); -AP_DECLARE(int) ap_event_pod_check(ap_event_pod_t * pod); -AP_DECLARE(apr_status_t) ap_event_pod_close(ap_event_pod_t * pod); -AP_DECLARE(apr_status_t) ap_event_pod_signal(ap_event_pod_t * pod, int graceful); -AP_DECLARE(void) ap_event_pod_killpg(ap_event_pod_t * pod, int num, int graceful); -/** @} */ diff --git a/server/mpm/worker/config3.m4 b/server/mpm/worker/config3.m4 index dc2bccb554..c28b73bf54 100644 --- a/server/mpm/worker/config3.m4 +++ b/server/mpm/worker/config3.m4 @@ -1,5 +1,5 @@ dnl ## XXX - Need a more thorough check of the proper flags to use -APACHE_MPM_MODULE(worker, $enable_mpm_worker, worker.lo fdqueue.lo pod.lo,[ +APACHE_MPM_MODULE(worker, $enable_mpm_worker, worker.lo fdqueue.lo,[ AC_CHECK_FUNCS(pthread_kill) ]) diff --git a/server/mpm/worker/pod.c b/server/mpm/worker/pod.c deleted file mode 100644 index 86f7b39d26..0000000000 --- a/server/mpm/worker/pod.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "apr_portable.h" -#include "pod.h" - -#if APR_HAVE_UNISTD_H -#include -#endif - -APLOG_USE_MODULE(mpm_worker); - -AP_DECLARE(apr_status_t) ap_worker_pod_open(apr_pool_t *p, ap_worker_pod_t **pod) -{ - apr_status_t rv; - - *pod = apr_palloc(p, sizeof(**pod)); - rv = apr_file_pipe_create(&((*pod)->pod_in), &((*pod)->pod_out), p); - if (rv != APR_SUCCESS) { - return rv; - } -/* - apr_file_pipe_timeout_set((*pod)->pod_in, 0); -*/ - (*pod)->p = p; - - /* close these before exec. */ - apr_file_inherit_unset((*pod)->pod_in); - apr_file_inherit_unset((*pod)->pod_out); - - return APR_SUCCESS; -} - -AP_DECLARE(int) ap_worker_pod_check(ap_worker_pod_t *pod) -{ - char c; - apr_os_file_t fd; - int rc; - - /* we need to surface EINTR so we'll have to grab the - * native file descriptor and do the OS read() ourselves - */ - apr_os_file_get(&fd, pod->pod_in); - rc = read(fd, &c, 1); - if (rc == 1) { - switch(c) { - case RESTART_CHAR: - return AP_RESTART; - case GRACEFUL_CHAR: - return AP_GRACEFUL; - } - } - return AP_NORESTART; -} - -AP_DECLARE(apr_status_t) ap_worker_pod_close(ap_worker_pod_t *pod) -{ - apr_status_t rv; - - rv = apr_file_close(pod->pod_out); - if (rv != APR_SUCCESS) { - return rv; - } - - rv = apr_file_close(pod->pod_in); - if (rv != APR_SUCCESS) { - return rv; - } - return rv; -} - -static apr_status_t pod_signal_internal(ap_worker_pod_t *pod, int graceful) -{ - apr_status_t rv; - char char_of_death = graceful ? GRACEFUL_CHAR : RESTART_CHAR; - apr_size_t one = 1; - - rv = apr_file_write(pod->pod_out, &char_of_death, &one); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00325) - "write pipe_of_death"); - } - return rv; -} - -AP_DECLARE(apr_status_t) ap_worker_pod_signal(ap_worker_pod_t *pod, int graceful) -{ - return pod_signal_internal(pod, graceful); -} - -AP_DECLARE(void) ap_worker_pod_killpg(ap_worker_pod_t *pod, int num, int graceful) -{ - int i; - apr_status_t rv = APR_SUCCESS; - - for (i = 0; i < num && rv == APR_SUCCESS; i++) { - rv = pod_signal_internal(pod, graceful); - } -} - diff --git a/server/mpm/worker/pod.h b/server/mpm/worker/pod.h deleted file mode 100644 index ccb9cf9d70..0000000000 --- a/server/mpm/worker/pod.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file worker/pod.h - * @brief Worker MPM Pipe of Death - * - * @addtogroup APACHE_MPM_WORKER - * @{ - */ - -#include "apr.h" -#include "apr_strings.h" -#define APR_WANT_STRFUNC -#include "apr_want.h" - -#include "httpd.h" -#include "http_config.h" -#include "http_log.h" -#include "http_main.h" -#include "mpm_common.h" -#include "ap_mpm.h" -#include "ap_listen.h" -#include "mpm_default.h" - -#define RESTART_CHAR '$' -#define GRACEFUL_CHAR '!' - -#define AP_RESTART 0 -#define AP_GRACEFUL 1 - -typedef struct ap_worker_pod_t ap_worker_pod_t; - -struct ap_worker_pod_t { - apr_file_t *pod_in; - apr_file_t *pod_out; - apr_pool_t *p; -}; - -AP_DECLARE(apr_status_t) ap_worker_pod_open(apr_pool_t *p, ap_worker_pod_t **pod); -AP_DECLARE(int) ap_worker_pod_check(ap_worker_pod_t *pod); -AP_DECLARE(apr_status_t) ap_worker_pod_close(ap_worker_pod_t *pod); -AP_DECLARE(apr_status_t) ap_worker_pod_signal(ap_worker_pod_t *pod, int graceful); -AP_DECLARE(void) ap_worker_pod_killpg(ap_worker_pod_t *pod, int num, int graceful); -/** @} */ diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index 8712e2fb9b..bf0d9e2c8c 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -58,7 +58,6 @@ #include "http_core.h" /* for get_remote_host */ #include "http_connection.h" #include "ap_mpm.h" -#include "pod.h" #include "mpm_common.h" #include "ap_listen.h" #include "scoreboard.h" @@ -189,7 +188,7 @@ typedef struct { #define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t) -static ap_worker_pod_t *pod; +static ap_pod_t *pod; /* The worker MPM respects a couple of runtime flags that can aid * in debugging. Setting the -DNO_DETACH flag will prevent the root process @@ -1339,24 +1338,24 @@ static void child_main(int child_num_arg) apr_signal(SIGTERM, dummy_signal_handler); /* Watch for any messages from the parent over the POD */ while (1) { - rv = ap_worker_pod_check(pod); - if (rv == AP_NORESTART) { + rv = ap_mpm_podx_check(pod); + if (rv == AP_MPM_PODX_NORESTART) { /* see if termination was triggered while we slept */ switch(terminate_mode) { case ST_GRACEFUL: - rv = AP_GRACEFUL; + rv = AP_MPM_PODX_GRACEFUL; break; case ST_UNGRACEFUL: - rv = AP_RESTART; + rv = AP_MPM_PODX_RESTART; break; } } - if (rv == AP_GRACEFUL || rv == AP_RESTART) { + if (rv == AP_MPM_PODX_GRACEFUL || rv == AP_MPM_PODX_RESTART) { /* make sure the start thread has finished; * signal_threads() and join_workers depend on that */ join_start_thread(start_thread_id); - signal_threads(rv == AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL); + signal_threads(rv == AP_MPM_PODX_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL); break; } } @@ -1582,7 +1581,7 @@ static void perform_idle_server_maintenance(void) if (idle_thread_count > max_spare_threads) { /* Kill off one child */ - ap_worker_pod_signal(pod, TRUE); + ap_mpm_podx_signal(pod, AP_MPM_PODX_GRACEFUL); retained->idle_spawn_rate = 1; } else if (idle_thread_count < min_spare_threads) { @@ -1837,7 +1836,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* Time to shut down: * Kill child processes, tell them to call child_exit, etc... */ - ap_worker_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_RESTART); ap_reclaim_child_processes(1, /* Start with SIGTERM */ worker_note_child_killed); @@ -1858,7 +1857,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) /* Close our listeners, and then ask our children to do same */ ap_close_listeners(); - ap_worker_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_GRACEFUL); ap_relieve_child_processes(worker_note_child_killed); if (!child_fatal) { @@ -1898,7 +1897,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) * way, try and make sure that all of our processes are * really dead. */ - ap_worker_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_RESTART); ap_reclaim_child_processes(1, worker_note_child_killed); return DONE; @@ -1923,7 +1922,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00297) AP_SIG_GRACEFUL_STRING " received. Doing graceful restart"); /* wake up the children...time to die. But we'll have more soon */ - ap_worker_pod_killpg(pod, ap_daemons_limit, TRUE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_GRACEFUL); /* This is mostly for debugging... so that we know what is still @@ -1936,7 +1935,7 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) * and a SIGHUP, we may as well use the same signal, because some user * pthreads are stealing signals from us left and right. */ - ap_worker_pod_killpg(pod, ap_daemons_limit, FALSE); + ap_mpm_podx_killpg(pod, ap_daemons_limit, AP_MPM_PODX_RESTART); ap_reclaim_child_processes(1, /* Start with SIGTERM */ worker_note_child_killed); @@ -1972,7 +1971,7 @@ static int worker_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, } if (!one_process) { - if ((rv = ap_worker_pod_open(pconf, &pod))) { + if ((rv = ap_mpm_podx_open(pconf, &pod))) { ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv, (startup ? NULL : s), "could not open pipe-of-death"); diff --git a/server/mpm_unix.c b/server/mpm_unix.c index 65c0940753..063af725f4 100644 --- a/server/mpm_unix.c +++ b/server/mpm_unix.c @@ -501,6 +501,107 @@ static apr_status_t pod_signal_internal(ap_pod_t *pod) return rv; } +AP_DECLARE(apr_status_t) ap_mpm_podx_open(apr_pool_t *p, ap_pod_t **pod) +{ + apr_status_t rv; + + *pod = apr_palloc(p, sizeof(**pod)); + rv = apr_file_pipe_create(&((*pod)->pod_in), &((*pod)->pod_out), p); + if (rv != APR_SUCCESS) { + return rv; + } + /* + apr_file_pipe_timeout_set((*pod)->pod_in, 0); + */ + (*pod)->p = p; + + /* close these before exec. */ + apr_file_inherit_unset((*pod)->pod_in); + apr_file_inherit_unset((*pod)->pod_out); + + return APR_SUCCESS; +} + +AP_DECLARE(int) ap_mpm_podx_check(ap_pod_t *pod) +{ + char c; + apr_os_file_t fd; + int rc; + + /* we need to surface EINTR so we'll have to grab the + * native file descriptor and do the OS read() ourselves + */ + apr_os_file_get(&fd, pod->pod_in); + rc = read(fd, &c, 1); + if (rc == 1) { + switch (c) { + case AP_MPM_PODX_RESTART_CHAR: + return AP_MPM_PODX_RESTART; + case AP_MPM_PODX_GRACEFUL_CHAR: + return AP_MPM_PODX_GRACEFUL; + } + } + return AP_MPM_PODX_NORESTART; +} + +AP_DECLARE(apr_status_t) ap_mpm_podx_close(ap_pod_t *pod) +{ + apr_status_t rv; + + rv = apr_file_close(pod->pod_out); + if (rv != APR_SUCCESS) { + return rv; + } + + rv = apr_file_close(pod->pod_in); + if (rv != APR_SUCCESS) { + return rv; + } + return rv; +} + +static apr_status_t podx_signal_internal(ap_pod_t *pod, + ap_podx_restart_t graceful) +{ + apr_status_t rv; + apr_size_t one = 1; + char char_of_death = ' '; + switch (graceful) { + case AP_MPM_PODX_RESTART: + char_of_death = AP_MPM_PODX_RESTART_CHAR; + break; + case AP_MPM_PODX_GRACEFUL: + char_of_death = AP_MPM_PODX_GRACEFUL_CHAR; + break; + case AP_MPM_PODX_NORESTART: + break; + } + + rv = apr_file_write(pod->pod_out, &char_of_death, &one); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(2404) + "write pipe_of_death"); + } + return rv; +} + +AP_DECLARE(apr_status_t) ap_mpm_podx_signal(ap_pod_t * pod, + ap_podx_restart_t graceful) +{ + return podx_signal_internal(pod, graceful); +} + +AP_DECLARE(void) ap_mpm_podx_killpg(ap_pod_t * pod, int num, + ap_podx_restart_t graceful) +{ + int i; + apr_status_t rv = APR_SUCCESS; + + for (i = 0; i < num && rv == APR_SUCCESS; i++) { + rv = podx_signal_internal(pod, graceful); + } +} + /* This function connects to the server and sends enough data to * ensure the child wakes up and processes a new connection. This * permits the MPM to skip the poll when there is only one listening