From: Jeff Trawick Date: Wed, 9 Apr 2003 16:58:30 +0000 (+0000) Subject: consolidate code related to sig_coredump X-Git-Tag: pre_ajp_proxy~1876 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=457570612ad2b473a71c0abf956e9da8d07b55d0;p=apache consolidate code related to sig_coredump a note on perchild: perchild exception handling was busted before this and is still busted the problem I noticed was that a client that exposes a segfault never gets its connection dropped and the parent never notices that the child process that segfaulted hasexited git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@99312 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/mpm_common.h b/include/mpm_common.h index 5961680089..ce58cedfb3 100644 --- a/include/mpm_common.h +++ b/include/mpm_common.h @@ -292,6 +292,11 @@ extern const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy, const char *arg); #endif +#ifdef AP_MPM_WANT_FATAL_SIGNAL_HANDLER +extern apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *pconf); +extern apr_status_t ap_fatal_signal_child_setup(server_rec *s); +#endif + #ifdef __cplusplus } #endif diff --git a/server/mpm/experimental/leader/leader.c b/server/mpm/experimental/leader/leader.c index 6f942da5c6..197e2cd005 100644 --- a/server/mpm/experimental/leader/leader.c +++ b/server/mpm/experimental/leader/leader.c @@ -459,33 +459,6 @@ static void clean_child_exit(int code) exit(code); } -/* handle all varieties of core dumping signals */ -static void sig_coredump(int sig) -{ - apr_filepath_set(ap_coredump_dir, pconf); - apr_signal(sig, SIG_DFL); - if (ap_my_pid == parent_pid) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, - 0, ap_server_conf, - "seg fault or similar nasty error detected " - "in the parent process"); - - /* XXX we can probably add some rudimentary cleanup code here, - * like getting rid of the pid file. If any additional bad stuff - * happens, we are protected from recursive errors taking down the - * system since this function is no longer the signal handler GLA - */ - } - kill(ap_my_pid, sig); - /* At this point we've got sig blocked, because we're still inside - * the signal handler. When we leave the signal handler it will - * be unblocked, and we'll take the signal... and coredump or whatever - * is appropriate for this particular Unix. In addition the parent - * will see the real signal we received -- whereas if we called - * abort() here, the parent would only see SIGABRT. - */ -} - static void just_die(int sig) { clean_child_exit(0); @@ -564,42 +537,16 @@ static void set_signals(void) { #ifndef NO_USE_SIGACTION struct sigaction sa; +#endif + + if (!one_process) { + ap_fatal_signal_setup(ap_server_conf, pconf); + } +#ifndef NO_USE_SIGACTION sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - if (!one_process) { - sa.sa_handler = sig_coredump; -#if defined(SA_ONESHOT) - sa.sa_flags = SA_ONESHOT; -#elif defined(SA_RESETHAND) - sa.sa_flags = SA_RESETHAND; -#endif - if (sigaction(SIGSEGV, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGSEGV)"); -#ifdef SIGBUS - if (sigaction(SIGBUS, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGBUS)"); -#endif -#ifdef SIGABORT - if (sigaction(SIGABORT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABORT)"); -#endif -#ifdef SIGABRT - if (sigaction(SIGABRT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABRT)"); -#endif -#ifdef SIGILL - if (sigaction(SIGILL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGILL)"); -#endif - sa.sa_flags = 0; - } sa.sa_handler = sig_term; if (sigaction(SIGTERM, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, @@ -641,19 +588,6 @@ static void set_signals(void) "sigaction(" AP_SIG_GRACEFUL_STRING ")"); #else if (!one_process) { - apr_signal(SIGSEGV, sig_coredump); -#ifdef SIGBUS - apr_signal(SIGBUS, sig_coredump); -#endif /* SIGBUS */ -#ifdef SIGABORT - apr_signal(SIGABORT, sig_coredump); -#endif /* SIGABORT */ -#ifdef SIGABRT - apr_signal(SIGABRT, sig_coredump); -#endif /* SIGABRT */ -#ifdef SIGILL - apr_signal(SIGILL, sig_coredump); -#endif /* SIGILL */ #ifdef SIGXCPU apr_signal(SIGXCPU, SIG_DFL); #endif /* SIGXCPU */ @@ -1104,6 +1038,7 @@ static void child_main(int child_num_arg) apr_thread_t *start_thread_id; ap_my_pid = getpid(); + ap_fatal_signal_child_setup(ap_server_conf); apr_pool_create(&pchild, pconf); /*stuff to do before we switch id's, so we have permissions.*/ diff --git a/server/mpm/experimental/leader/mpm.h b/server/mpm/experimental/leader/mpm.h index 9f763b7111..8bf78e5577 100644 --- a/server/mpm/experimental/leader/mpm.h +++ b/server/mpm/experimental/leader/mpm.h @@ -76,6 +76,7 @@ #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH #define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_WANT_SET_MAX_MEM_FREE +#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define AP_MPM_USES_POD 1 diff --git a/server/mpm/experimental/perchild/mpm.h b/server/mpm/experimental/perchild/mpm.h index 618298707f..d6c8ce41e3 100644 --- a/server/mpm/experimental/perchild/mpm.h +++ b/server/mpm/experimental/perchild/mpm.h @@ -77,6 +77,7 @@ #define AP_MPM_WANT_SET_COREDUMPDIR #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH #define AP_MPM_WANT_SIGNAL_SERVER +#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER #define AP_MPM_USES_POD #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) diff --git a/server/mpm/experimental/perchild/perchild.c b/server/mpm/experimental/perchild/perchild.c index 0978480226..04a0dba197 100644 --- a/server/mpm/experimental/perchild/perchild.c +++ b/server/mpm/experimental/perchild/perchild.c @@ -324,21 +324,6 @@ static void clean_child_exit(int code) exit(code); } -/* handle all varieties of core dumping signals */ -static void sig_coredump(int sig) -{ - chdir(ap_coredump_dir); - apr_signal(sig, SIG_DFL); - kill(getpid(), sig); - /* At this point we've got sig blocked, because we're still inside - * the signal handler. When we leave the signal handler it will - * be unblocked, and we'll take the signal... and coredump or whatever - * is appropriate for this particular Unix. In addition the parent - * will see the real signal we received -- whereas if we called - * abort() here, the parent would only see SIGABRT. - */ -} - static void just_die(int sig) { clean_child_exit(0); @@ -418,42 +403,16 @@ static void set_signals(void) { #ifndef NO_USE_SIGACTION struct sigaction sa; +#endif + if (!one_process) { + ap_fatal_signal_setup(ap_server_conf, pconf); + } + +#ifndef NO_USE_SIGACTION sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - if (!one_process) { - sa.sa_handler = sig_coredump; -#if defined(SA_ONESHOT) - sa.sa_flags = SA_ONESHOT; -#elif defined(SA_RESETHAND) - sa.sa_flags = SA_RESETHAND; -#endif - if (sigaction(SIGSEGV, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGSEGV)"); -#ifdef SIGBUS - if (sigaction(SIGBUS, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGBUS)"); -#endif -#ifdef SIGABORT - if (sigaction(SIGABORT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABORT)"); -#endif -#ifdef SIGABRT - if (sigaction(SIGABRT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABRT)"); -#endif -#ifdef SIGILL - if (sigaction(SIGILL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGILL)"); -#endif - sa.sa_flags = 0; - } sa.sa_handler = sig_term; if (sigaction(SIGTERM, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, @@ -495,19 +454,6 @@ static void set_signals(void) "sigaction(" AP_SIG_GRACEFUL_STRING ")"); #else if (!one_process) { - apr_signal(SIGSEGV, sig_coredump); -#ifdef SIGBUS - apr_signal(SIGBUS, sig_coredump); -#endif /* SIGBUS */ -#ifdef SIGABORT - apr_signal(SIGABORT, sig_coredump); -#endif /* SIGABORT */ -#ifdef SIGABRT - apr_signal(SIGABRT, sig_coredump); -#endif /* SIGABRT */ -#ifdef SIGILL - apr_signal(SIGILL, sig_coredump); -#endif /* SIGILL */ #ifdef SIGXCPU apr_signal(SIGXCPU, SIG_DFL); #endif /* SIGXCPU */ @@ -1025,6 +971,7 @@ static void child_main(int child_num_arg) ap_listen_rec *lr; my_pid = getpid(); + ap_fatal_signal_child_setup(ap_server_conf); child_num = child_num_arg; apr_pool_create(&pchild, pconf); diff --git a/server/mpm/experimental/threadpool/mpm.h b/server/mpm/experimental/threadpool/mpm.h index f28f666d7f..ba1de13fa0 100644 --- a/server/mpm/experimental/threadpool/mpm.h +++ b/server/mpm/experimental/threadpool/mpm.h @@ -76,6 +76,7 @@ #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH #define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_WANT_SET_MAX_MEM_FREE +#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) diff --git a/server/mpm/experimental/threadpool/threadpool.c b/server/mpm/experimental/threadpool/threadpool.c index 3f70345ac1..14388c1038 100644 --- a/server/mpm/experimental/threadpool/threadpool.c +++ b/server/mpm/experimental/threadpool/threadpool.c @@ -535,33 +535,6 @@ static void clean_child_exit(int code) exit(code); } -/* handle all varieties of core dumping signals */ -static void sig_coredump(int sig) -{ - apr_filepath_set(ap_coredump_dir, pconf); - apr_signal(sig, SIG_DFL); - if (ap_my_pid == parent_pid) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, - 0, ap_server_conf, - "seg fault or similar nasty error detected " - "in the parent process"); - - /* XXX we can probably add some rudimentary cleanup code here, - * like getting rid of the pid file. If any additional bad stuff - * happens, we are protected from recursive errors taking down the - * system since this function is no longer the signal handler GLA - */ - } - kill(ap_my_pid, sig); - /* At this point we've got sig blocked, because we're still inside - * the signal handler. When we leave the signal handler it will - * be unblocked, and we'll take the signal... and coredump or whatever - * is appropriate for this particular Unix. In addition the parent - * will see the real signal we received -- whereas if we called - * abort() here, the parent would only see SIGABRT. - */ -} - static void just_die(int sig) { clean_child_exit(0); @@ -635,42 +608,16 @@ static void set_signals(void) { #ifndef NO_USE_SIGACTION struct sigaction sa; +#endif + if (!one_process) { + ap_fatal_signal_setup(ap_server_conf, pconf); + } + +#ifndef NO_USE_SIGACTION sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - if (!one_process) { - sa.sa_handler = sig_coredump; -#if defined(SA_ONESHOT) - sa.sa_flags = SA_ONESHOT; -#elif defined(SA_RESETHAND) - sa.sa_flags = SA_RESETHAND; -#endif - if (sigaction(SIGSEGV, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGSEGV)"); -#ifdef SIGBUS - if (sigaction(SIGBUS, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGBUS)"); -#endif -#ifdef SIGABORT - if (sigaction(SIGABORT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABORT)"); -#endif -#ifdef SIGABRT - if (sigaction(SIGABRT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABRT)"); -#endif -#ifdef SIGILL - if (sigaction(SIGILL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGILL)"); -#endif - sa.sa_flags = 0; - } sa.sa_handler = sig_term; if (sigaction(SIGTERM, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, @@ -712,19 +659,6 @@ static void set_signals(void) "sigaction(" AP_SIG_GRACEFUL_STRING ")"); #else if (!one_process) { - apr_signal(SIGSEGV, sig_coredump); -#ifdef SIGBUS - apr_signal(SIGBUS, sig_coredump); -#endif /* SIGBUS */ -#ifdef SIGABORT - apr_signal(SIGABORT, sig_coredump); -#endif /* SIGABORT */ -#ifdef SIGABRT - apr_signal(SIGABRT, sig_coredump); -#endif /* SIGABRT */ -#ifdef SIGILL - apr_signal(SIGILL, sig_coredump); -#endif /* SIGILL */ #ifdef SIGXCPU apr_signal(SIGXCPU, SIG_DFL); #endif /* SIGXCPU */ @@ -1322,6 +1256,7 @@ static void child_main(int child_num_arg) apr_thread_t *start_thread_id; ap_my_pid = getpid(); + ap_fatal_signal_child_setup(ap_server_conf); apr_pool_create(&pchild, pconf); /*stuff to do before we switch id's, so we have permissions.*/ diff --git a/server/mpm/prefork/mpm.h b/server/mpm/prefork/mpm.h index 7ebce7c54d..8006f7ed2e 100644 --- a/server/mpm/prefork/mpm.h +++ b/server/mpm/prefork/mpm.h @@ -79,6 +79,7 @@ #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH #define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_WANT_SET_MAX_MEM_FREE +#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define AP_MPM_USES_POD 1 diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index 64aea20367..cab24ddb1a 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -353,27 +353,6 @@ int reap_children(int *exitcode, apr_exit_why_e *status) } #endif -/* handle all varieties of core dumping signals */ -static void sig_coredump(int sig) -{ - chdir(ap_coredump_dir); - apr_signal(sig, SIG_DFL); - if (ap_my_pid == parent_pid) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, - 0, ap_server_conf, - "seg fault or similar nasty error detected " - "in the parent process"); - } - kill(getpid(), sig); - /* At this point we've got sig blocked, because we're still inside - * the signal handler. When we leave the signal handler it will - * be unblocked, and we'll take the signal... and coredump or whatever - * is appropriate for this particular Unix. In addition the parent - * will see the real signal we received -- whereas if we called - * abort() here, the parent would only see SIGABRT. - */ -} - /***************************************************************** * Connection structures and accounting... */ @@ -417,37 +396,16 @@ static void set_signals(void) { #ifndef NO_USE_SIGACTION struct sigaction sa; +#endif + + if (!one_process) { + ap_fatal_signal_setup(ap_server_conf, pconf); + } +#ifndef NO_USE_SIGACTION sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - if (!one_process) { - sa.sa_handler = sig_coredump; -#if defined(SA_ONESHOT) - sa.sa_flags = SA_ONESHOT; -#elif defined(SA_RESETHAND) - sa.sa_flags = SA_RESETHAND; -#endif - if (sigaction(SIGSEGV, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGSEGV)"); -#ifdef SIGBUS - if (sigaction(SIGBUS, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGBUS)"); -#endif -#ifdef SIGABORT - if (sigaction(SIGABORT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABORT)"); -#endif -#ifdef SIGABRT - if (sigaction(SIGABRT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGABRT)"); -#endif -#ifdef SIGILL - if (sigaction(SIGILL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGILL)"); -#endif - sa.sa_flags = 0; - } sa.sa_handler = sig_term; if (sigaction(SIGTERM, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)"); @@ -482,19 +440,6 @@ static void set_signals(void) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")"); #else if (!one_process) { - apr_signal(SIGSEGV, sig_coredump); -#ifdef SIGBUS - apr_signal(SIGBUS, sig_coredump); -#endif /* SIGBUS */ -#ifdef SIGABORT - apr_signal(SIGABORT, sig_coredump); -#endif /* SIGABORT */ -#ifdef SIGABRT - apr_signal(SIGABRT, sig_coredump); -#endif /* SIGABRT */ -#ifdef SIGILL - apr_signal(SIGILL, sig_coredump); -#endif /* SIGILL */ #ifdef SIGXCPU apr_signal(SIGXCPU, SIG_DFL); #endif /* SIGXCPU */ @@ -555,6 +500,8 @@ static void child_main(int child_num_arg) csd = NULL; requests_this_child = 0; + ap_fatal_signal_child_setup(ap_server_conf); + /* Get a sub context for global allocations in this child, so that * we can have cleanups occur when the child exits. */ diff --git a/server/mpm/worker/mpm.h b/server/mpm/worker/mpm.h index bf84e1d6b8..9e6429ee5d 100644 --- a/server/mpm/worker/mpm.h +++ b/server/mpm/worker/mpm.h @@ -76,6 +76,7 @@ #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH #define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_WANT_SET_MAX_MEM_FREE +#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index 50f350381b..1f35249120 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -374,33 +374,6 @@ static void clean_child_exit(int code) exit(code); } -/* handle all varieties of core dumping signals */ -static void sig_coredump(int sig) -{ - apr_filepath_set(ap_coredump_dir, pconf); - apr_signal(sig, SIG_DFL); - if (ap_my_pid == parent_pid) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, - 0, ap_server_conf, - "seg fault or similar nasty error detected " - "in the parent process"); - - /* XXX we can probably add some rudimentary cleanup code here, - * like getting rid of the pid file. If any additional bad stuff - * happens, we are protected from recursive errors taking down the - * system since this function is no longer the signal handler GLA - */ - } - kill(ap_my_pid, sig); - /* At this point we've got sig blocked, because we're still inside - * the signal handler. When we leave the signal handler it will - * be unblocked, and we'll take the signal... and coredump or whatever - * is appropriate for this particular Unix. In addition the parent - * will see the real signal we received -- whereas if we called - * abort() here, the parent would only see SIGABRT. - */ -} - static void just_die(int sig) { clean_child_exit(0); @@ -474,42 +447,16 @@ static void set_signals(void) { #ifndef NO_USE_SIGACTION struct sigaction sa; +#endif + if (!one_process) { + ap_fatal_signal_setup(ap_server_conf, pconf); + } + +#ifndef NO_USE_SIGACTION sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - if (!one_process) { - sa.sa_handler = sig_coredump; -#if defined(SA_ONESHOT) - sa.sa_flags = SA_ONESHOT; -#elif defined(SA_RESETHAND) - sa.sa_flags = SA_RESETHAND; -#endif - if (sigaction(SIGSEGV, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGSEGV)"); -#ifdef SIGBUS - if (sigaction(SIGBUS, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGBUS)"); -#endif -#ifdef SIGABORT - if (sigaction(SIGABORT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABORT)"); -#endif -#ifdef SIGABRT - if (sigaction(SIGABRT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGABRT)"); -#endif -#ifdef SIGILL - if (sigaction(SIGILL, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, - "sigaction(SIGILL)"); -#endif - sa.sa_flags = 0; - } sa.sa_handler = sig_term; if (sigaction(SIGTERM, &sa, NULL) < 0) ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, @@ -551,19 +498,6 @@ static void set_signals(void) "sigaction(" AP_SIG_GRACEFUL_STRING ")"); #else if (!one_process) { - apr_signal(SIGSEGV, sig_coredump); -#ifdef SIGBUS - apr_signal(SIGBUS, sig_coredump); -#endif /* SIGBUS */ -#ifdef SIGABORT - apr_signal(SIGABORT, sig_coredump); -#endif /* SIGABORT */ -#ifdef SIGABRT - apr_signal(SIGABRT, sig_coredump); -#endif /* SIGABRT */ -#ifdef SIGILL - apr_signal(SIGILL, sig_coredump); -#endif /* SIGILL */ #ifdef SIGXCPU apr_signal(SIGXCPU, SIG_DFL); #endif /* SIGXCPU */ @@ -1194,6 +1128,7 @@ static void child_main(int child_num_arg) apr_thread_t *start_thread_id; ap_my_pid = getpid(); + ap_fatal_signal_child_setup(ap_server_conf); apr_pool_create(&pchild, pconf); /*stuff to do before we switch id's, so we have permissions.*/ diff --git a/server/mpm_common.c b/server/mpm_common.c index 0632ed63ba..e55a8ee2b6 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -97,6 +97,9 @@ #ifdef HAVE_GRP_H #include #endif +#if APR_HAVE_UNISTD_H +#include +#endif #ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES void ap_reclaim_child_processes(int terminate) @@ -910,3 +913,101 @@ const char *ap_mpm_set_max_mem_free(cmd_parms *cmd, void *dummy, } #endif /* AP_MPM_WANT_SET_MAX_MEM_FREE */ + +#ifdef AP_MPM_WANT_FATAL_SIGNAL_HANDLER + +static pid_t parent_pid, my_pid; +apr_pool_t *pconf; + +/* handle all varieties of core dumping signals */ +static void sig_coredump(int sig) +{ + apr_filepath_set(ap_coredump_dir, pconf); + apr_signal(sig, SIG_DFL); + if (my_pid == parent_pid) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, + 0, ap_server_conf, + "seg fault or similar nasty error detected " + "in the parent process"); + /* XXX we can probably add some rudimentary cleanup code here, + * like getting rid of the pid file. If any additional bad stuff + * happens, we are protected from recursive errors taking down the + * system since this function is no longer the signal handler GLA + */ + } + kill(getpid(), sig); + /* At this point we've got sig blocked, because we're still inside + * the signal handler. When we leave the signal handler it will + * be unblocked, and we'll take the signal... and coredump or whatever + * is appropriate for this particular Unix. In addition the parent + * will see the real signal we received -- whereas if we called + * abort() here, the parent would only see SIGABRT. + */ +} + +apr_status_t ap_fatal_signal_child_setup(server_rec *s) +{ + my_pid = getpid(); + return APR_SUCCESS; +} + +apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf) +{ +#ifndef NO_USE_SIGACTION + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + +#if defined(SA_ONESHOT) + sa.sa_flags = SA_ONESHOT; +#elif defined(SA_RESETHAND) + sa.sa_flags = SA_RESETHAND; +#else + sa.sa_flags = 0; +#endif + + sa.sa_handler = sig_coredump; + if (sigaction(SIGSEGV, &sa, NULL) < 0) + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGSEGV)"); +#ifdef SIGBUS + if (sigaction(SIGBUS, &sa, NULL) < 0) + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGBUS)"); +#endif +#ifdef SIGABORT + if (sigaction(SIGABORT, &sa, NULL) < 0) + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGABORT)"); +#endif +#ifdef SIGABRT + if (sigaction(SIGABRT, &sa, NULL) < 0) + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGABRT)"); +#endif +#ifdef SIGILL + if (sigaction(SIGILL, &sa, NULL) < 0) + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGILL)"); +#endif + +#else /* NO_USE_SIGACTION */ + + apr_signal(SIGSEGV, sig_coredump); +#ifdef SIGBUS + apr_signal(SIGBUS, sig_coredump); +#endif /* SIGBUS */ +#ifdef SIGABORT + apr_signal(SIGABORT, sig_coredump); +#endif /* SIGABORT */ +#ifdef SIGABRT + apr_signal(SIGABRT, sig_coredump); +#endif /* SIGABRT */ +#ifdef SIGILL + apr_signal(SIGILL, sig_coredump); +#endif /* SIGILL */ + +#endif /* NO_USE_SIGACTION */ + + pconf = in_pconf; + parent_pid = my_pid = getpid(); + + return APR_SUCCESS; +} + +#endif /* AP_MPM_WANT_FATAL_SIGNAL_HANDLER */