[apache2] 05/09: Fix Apache crash on restarts (ASF Bug 61558)

Ondřej Surý ondrej at debian.org
Tue Oct 24 18:36:01 UTC 2017


This is an automated email from the git hooks/post-receive script.

ondrej pushed a commit to branch master
in repository apache2.

commit b85d6b526aa2978ce318f1a15bdcaba39f79631f
Author: Ondřej Surý <ondrej at sury.org>
Date:   Thu Sep 28 17:53:26 2017 +0200

    Fix Apache crash on restarts (ASF Bug 61558)
---
 ...-hooks-cleanup-on-exit-v3-2.4.x-for-bug-6.patch | 228 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 2 files changed, 229 insertions(+)

diff --git a/debian/patches/0011-Signals-and-hooks-cleanup-on-exit-v3-2.4.x-for-bug-6.patch b/debian/patches/0011-Signals-and-hooks-cleanup-on-exit-v3-2.4.x-for-bug-6.patch
new file mode 100644
index 0000000..99d0a31
--- /dev/null
+++ b/debian/patches/0011-Signals-and-hooks-cleanup-on-exit-v3-2.4.x-for-bug-6.patch
@@ -0,0 +1,228 @@
+From: =?utf-8?q?Ond=C5=99ej_Sur=C3=BD?= <ondrej at sury.org>
+Date: Thu, 28 Sep 2017 17:51:59 +0200
+Subject: Signals and hooks cleanup on exit (v3, 2.4.x) for bug #61558
+
+---
+ os/unix/unixd.c              | 24 ++++++++++++++++++++++++
+ server/main.c                | 33 ++++++++++++++++++++++++++++-----
+ server/mpm/event/event.c     |  3 ---
+ server/mpm/prefork/prefork.c |  3 ---
+ server/mpm/worker/worker.c   |  3 ---
+ server/mpm_unix.c            | 29 +++++++++++++++++++++++++++++
+ 6 files changed, 81 insertions(+), 14 deletions(-)
+
+diff --git a/os/unix/unixd.c b/os/unix/unixd.c
+index 07a9bef..7f71d1a 100644
+--- a/os/unix/unixd.c
++++ b/os/unix/unixd.c
+@@ -437,11 +437,19 @@ AP_DECLARE(apr_status_t) ap_unixd_accept(void **accepted, ap_listen_rec *lr,
+ /* Unixes MPMs' */
+ 
+ static ap_unixd_mpm_retained_data *retained_data = NULL;
++static apr_status_t retained_data_cleanup(void *unused)
++{
++    (void)unused;
++    retained_data = NULL;
++    return APR_SUCCESS;
++}
++
+ AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data()
+ {
+     if (!retained_data) {
+         retained_data = ap_retained_data_create("ap_unixd_mpm_retained_data",
+                                                 sizeof(*retained_data));
++        apr_pool_pre_cleanup_register(ap_pglobal, NULL, retained_data_cleanup);
+         retained_data->mpm_state = AP_MPMQ_STARTING;
+     }
+     return retained_data;
+@@ -449,6 +457,10 @@ AP_DECLARE(ap_unixd_mpm_retained_data *) ap_unixd_mpm_get_retained_data()
+ 
+ static void sig_term(int sig)
+ {
++    if (!retained_data) {
++        /* Main process (ap_pglobal) is dying */
++        return;
++    }
+     retained_data->mpm_state = AP_MPMQ_STOPPING;
+     if (retained_data->shutdown_pending
+             && (retained_data->is_ungraceful
+@@ -465,6 +477,10 @@ static void sig_term(int sig)
+ 
+ static void sig_restart(int sig)
+ {
++    if (!retained_data) {
++        /* Main process (ap_pglobal) is dying */
++        return;
++    }
+     retained_data->mpm_state = AP_MPMQ_STOPPING;
+     if (retained_data->restart_pending
+             && (retained_data->is_ungraceful
+@@ -481,6 +497,10 @@ static void sig_restart(int sig)
+ 
+ static apr_status_t unset_signals(void *unused)
+ {
++    if (!retained_data) {
++        /* Main process (ap_pglobal) is dying */
++        return APR_SUCCESS;
++    }
+     retained_data->shutdown_pending = retained_data->restart_pending = 0;
+     retained_data->was_graceful = !retained_data->is_ungraceful;
+     retained_data->is_ungraceful = 0;
+@@ -494,6 +514,10 @@ AP_DECLARE(void) ap_unixd_mpm_set_signals(apr_pool_t *pconf, int one_process)
+     struct sigaction sa;
+ #endif
+ 
++    if (!one_process) {
++        ap_fatal_signal_setup(ap_server_conf, pconf);
++    }
++
+     /* Signals' handlers depend on retained data */
+     (void)ap_unixd_mpm_get_retained_data();
+ 
+diff --git a/server/main.c b/server/main.c
+index ba9d91c..edfbb0c 100644
+--- a/server/main.c
++++ b/server/main.c
+@@ -273,6 +273,30 @@ static int abort_on_oom(int retcode)
+     return retcode; /* unreachable, hopefully. */
+ }
+ 
++/* Deregister all hooks when clearing pconf (pre_cleanup).
++ * TODO: have a hook to deregister and run them from here?
++ *       ap_clear_auth_internal() is already a candidate.
++ */
++static apr_status_t deregister_all_hooks(void *unused)
++{
++    (void)unused;
++    ap_clear_auth_internal();
++    apr_hook_deregister_all();
++    return APR_SUCCESS;
++}
++
++static void reset_process_pconf(process_rec *process)
++{
++    if (process->pconf) {
++        apr_pool_clear(process->pconf);
++    }
++    else {
++        apr_pool_create(&process->pconf, process->pool);
++        apr_pool_tag(process->pconf, "pconf");
++    }
++    apr_pool_pre_cleanup_register(process->pconf, NULL, deregister_all_hooks);
++}
++
+ static process_rec *init_process(int *argc, const char * const * *argv)
+ {
+     process_rec *process;
+@@ -317,8 +341,9 @@ static process_rec *init_process(int *argc, const char * const * *argv)
+     process = apr_palloc(cntx, sizeof(process_rec));
+     process->pool = cntx;
+ 
+-    apr_pool_create(&process->pconf, process->pool);
+-    apr_pool_tag(process->pconf, "pconf");
++    process->pconf = NULL;
++    reset_process_pconf(process);
++
+     process->argc = *argc;
+     process->argv = *argv;
+     process->short_name = apr_filepath_name_get((*argv)[0]);
+@@ -718,9 +743,7 @@ int main(int argc, const char * const argv[])
+ 
+     do {
+         ap_main_state = AP_SQ_MS_DESTROY_CONFIG;
+-        apr_hook_deregister_all();
+-        apr_pool_clear(pconf);
+-        ap_clear_auth_internal();
++        reset_process_pconf(process);
+ 
+         ap_main_state = AP_SQ_MS_CREATE_CONFIG;
+         ap_config_generation++;
+diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c
+index 6bbc8e5..312991e 100644
+--- a/server/mpm/event/event.c
++++ b/server/mpm/event/event.c
+@@ -2685,9 +2685,6 @@ static int event_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
+         ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
+     }
+ 
+-    if (!one_process) {
+-        ap_fatal_signal_setup(ap_server_conf, pconf);
+-    }
+     ap_unixd_mpm_set_signals(pconf, one_process);
+ 
+     /* Don't thrash since num_buckets depends on the
+diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
+index 559f90a..619eace 100644
+--- a/server/mpm/prefork/prefork.c
++++ b/server/mpm/prefork/prefork.c
+@@ -853,9 +853,6 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
+         ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
+     }
+ 
+-    if (!one_process) {
+-        ap_fatal_signal_setup(ap_server_conf, pconf);
+-    }
+     ap_unixd_mpm_set_signals(pconf, one_process);
+ 
+     if (one_process) {
+diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c
+index d2147bf..776ae7f 100644
+--- a/server/mpm/worker/worker.c
++++ b/server/mpm/worker/worker.c
+@@ -1671,9 +1671,6 @@ static int worker_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
+         ap_scoreboard_image->global->running_generation = retained->mpm->my_generation;
+     }
+ 
+-    if (!one_process) {
+-        ap_fatal_signal_setup(ap_server_conf, pconf);
+-    }
+     ap_unixd_mpm_set_signals(pconf, one_process);
+ 
+     /* Don't thrash since num_buckets depends on the
+diff --git a/server/mpm_unix.c b/server/mpm_unix.c
+index 2f3d20e..1800f5d 100644
+--- a/server/mpm_unix.c
++++ b/server/mpm_unix.c
+@@ -1009,6 +1009,33 @@ AP_DECLARE(apr_status_t) ap_fatal_signal_child_setup(server_rec *s)
+     return APR_SUCCESS;
+ }
+ 
++/* We can't call sig_coredump (ap_log_error) once pconf is destroyed, so
++ * avoid double faults by restoring each default signal handler on cleanup.
++ */
++static apr_status_t fatal_signal_cleanup(void *unused)
++{
++    (void)unused;
++
++    apr_signal(SIGSEGV, SIG_DFL);
++#ifdef SIGBUS
++    apr_signal(SIGBUS, SIG_DFL);
++#endif /* SIGBUS */
++#ifdef SIGABORT
++    apr_signal(SIGABORT, SIG_DFL);
++#endif /* SIGABORT */
++#ifdef SIGABRT
++    apr_signal(SIGABRT, SIG_DFL);
++#endif /* SIGABRT */
++#ifdef SIGILL
++    apr_signal(SIGILL, SIG_DFL);
++#endif /* SIGILL */
++#ifdef SIGFPE
++    apr_signal(SIGFPE, SIG_DFL);
++#endif /* SIGFPE */
++
++    return APR_SUCCESS;
++}
++
+ AP_DECLARE(apr_status_t) ap_fatal_signal_setup(server_rec *s,
+                                                apr_pool_t *in_pconf)
+ {
+@@ -1071,6 +1098,8 @@ AP_DECLARE(apr_status_t) ap_fatal_signal_setup(server_rec *s,
+ 
+     pconf = in_pconf;
+     parent_pid = my_pid = getpid();
++    apr_pool_cleanup_register(pconf, NULL, fatal_signal_cleanup,
++                              fatal_signal_cleanup);
+ 
+     return APR_SUCCESS;
+ }
diff --git a/debian/patches/series b/debian/patches/series
index 6e395fa..53273b5 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -10,3 +10,4 @@ reproducible_builds.diff
 
 fix_logresolve_segfault.patch
 mod_ssl_md-2.4.x-v5.diff
+0011-Signals-and-hooks-cleanup-on-exit-v3-2.4.x-for-bug-6.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-apache/apache2.git



More information about the Pkg-apache-commits mailing list