From: Jeff Trawick Date: Wed, 28 Jan 2004 21:22:21 +0000 (+0000) Subject: Add fatal exception hook for running diagnostic code after a X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=df2bbe714ce23461c1c411e8e916f29e0c45f9e2;p=thirdparty%2Fapache%2Fhttpd.git Add fatal exception hook for running diagnostic code after a crash. Reviewed by: Bill Stoddard, Mads Toftum git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@102436 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/STATUS b/STATUS index fd317486d85..96a464b0472 100644 --- a/STATUS +++ b/STATUS @@ -1,5 +1,5 @@ APACHE 1.3 STATUS: -*-text-*- - Last modified at [$Date: 2004/01/28 18:26:38 $] + Last modified at [$Date: 2004/01/28 21:22:20 $] Release: @@ -49,16 +49,6 @@ RELEASE SHOWSTOPPERS: RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP: - * fatal exception hook feature - discussion: - Message-Id: <400D4774.9020304@attglobal.net> - and followups - patch to consider: - http://www.apache.org/~trawick/13_fatal_exception_patch.20040124 - proof-of-concept modules described at - http://www.apache.org/~trawick/exception_hook_13.html - +1: trawick, stoddard - * isn't ap_die() broken with recognizing recursive errors Message-Id: <3F8C56E3.8050501@attglobal.net> +1: jeff, jim diff --git a/src/CHANGES b/src/CHANGES index b7afc546789..6c37c81846b 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,8 @@ Changes with Apache 1.3.30 + *) Add fatal exception hook for running diagnostic code after a + crash. [Jeff Trawick] + *) Make REMOTE_PORT variable available in mod_rewrite. PR 25772. [André Malo] diff --git a/src/include/ap_config.h b/src/include/ap_config.h index 62bc79bc884..17235c5cd6d 100644 --- a/src/include/ap_config.h +++ b/src/include/ap_config.h @@ -193,6 +193,7 @@ typedef int rlim_t; int gethostname(char *name, int namelen); #define HAVE_SYSLOG 1 #define SYS_SIGLIST _sys_siglist +#define AP_ENABLE_EXCEPTION_HOOK #elif defined(IRIX) #undef HAVE_GMTOFF @@ -299,6 +300,7 @@ typedef int rlim_t; #elif AIX >= 420 #define NET_SIZE_T size_t #endif +#define AP_ENABLE_EXCEPTION_HOOK #elif defined(ULTRIX) /* we don't want to use sys/resource.h under @@ -521,6 +523,7 @@ typedef int pid_t; #if !defined(__GLIBC__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1) typedef int rlim_t; #endif +#define AP_ENABLE_EXCEPTION_HOOK #elif defined(SCO) #undef HAVE_GMTOFF diff --git a/src/include/http_conf_globals.h b/src/include/http_conf_globals.h index dba479f7fab..e102481f695 100644 --- a/src/include/http_conf_globals.h +++ b/src/include/http_conf_globals.h @@ -100,6 +100,9 @@ extern API_VAR_EXPORT char *ap_pid_fname; extern API_VAR_EXPORT char *ap_scoreboard_fname; extern API_VAR_EXPORT char *ap_lock_fname; extern API_VAR_EXPORT char *ap_server_argv0; +#ifdef AP_ENABLE_EXCEPTION_HOOK +extern int ap_exception_hook_enabled; +#endif extern enum server_token_type ap_server_tokens; diff --git a/src/include/httpd.h b/src/include/httpd.h index 9e758eaf4eb..682ba12c9e7 100644 --- a/src/include/httpd.h +++ b/src/include/httpd.h @@ -1226,6 +1226,32 @@ API_EXPORT(extern const char *) ap_psignature(const char *prefix, request_rec *r #endif #define strtoul strtoul_is_not_a_portable_function_use_strtol_instead +#ifdef AP_ENABLE_EXCEPTION_HOOK +/* The exception hook allows a module to run from the server's signal + * handler, and perform tasks such as logging the current request or + * getting a backtrace or performing other diagnostic functions. All + * operating system requirements for running in a signal handler must + * be respected, or the process may not exit properly. + * + * AP_ENABLE_EXCEPTION_HOOK is already defined for platforms that have + * been tested. It likely will work on other platforms. In order to + * test, define AP_ENABLE_EXCEPTION_HOOK at configure time. + */ +typedef struct ap_exception_info_t { + int sig; + pid_t pid; +} ap_exception_info_t; + +/* Register a function to be called after a fatal exception (on *X systems, a + * "synchronous signal" such as SIGSEGV, SIGILL, etc.). + * + * Returns 0 on success, non-zero on failure. + * If EnableExceptionHook directive is not set to "on", this function will + * report failure and no such hooks will be called. + */ +API_EXPORT(extern int) ap_add_fatal_exception_hook(void (*fn)(ap_exception_info_t *)); +#endif /* AP_ENABLE_EXCEPTION_HOOK */ + #ifdef __cplusplus } #endif diff --git a/src/main/http_core.c b/src/main/http_core.c index dfb78d1ca43..80c36a88688 100644 --- a/src/main/http_core.c +++ b/src/main/http_core.c @@ -2248,6 +2248,32 @@ static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy, char *arg) return NULL; } +#ifdef AP_ENABLE_EXCEPTION_HOOK +static const char *set_exception_hook(cmd_parms *cmd, void *dummy, char *arg) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + + if (cmd->server->is_virtual) { + return "EnableExceptionHook directive not allowed in "; + } + + if (strcasecmp(arg, "on") == 0) { + ap_exception_hook_enabled = 1; + } + else if (strcasecmp(arg, "off") == 0) { + ap_exception_hook_enabled = 0; + } + else { + return "parameter must be 'on' or 'off'"; + } + + return NULL; +} +#endif /* AP_ENABLE_EXCEPTION_HOOK */ + static const char *set_pidfile(cmd_parms *cmd, void *dummy, char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); @@ -3628,6 +3654,10 @@ static const command_rec core_cmds[] = { #endif "are compiled in" }, +#ifdef AP_ENABLE_EXCEPTION_HOOK +{ "EnableExceptionHook", set_exception_hook, NULL, RSRC_CONF, TAKE1, + "Controls whether exception hook may be called after a crash" }, +#endif /* EBCDIC Conversion directives: */ #ifdef CHARSET_EBCDIC diff --git a/src/main/http_main.c b/src/main/http_main.c index 38795f18717..9b6142a94a6 100644 --- a/src/main/http_main.c +++ b/src/main/http_main.c @@ -260,6 +260,9 @@ API_VAR_EXPORT int ap_daemons_limit=0; API_VAR_EXPORT time_t ap_restart_time=0; API_VAR_EXPORT int ap_suexec_enabled = 0; API_VAR_EXPORT int ap_listenbacklog=0; +#ifdef AP_ENABLE_EXCEPTION_HOOK +int ap_exception_hook_enabled=0; +#endif struct accept_mutex_methods_s { void (*child_init)(pool *p); @@ -3110,12 +3113,63 @@ static void siglist_init(void) } #endif /* platform has sys_siglist[] */ +#ifdef AP_ENABLE_EXCEPTION_HOOK +typedef struct except_hook_t { + struct except_hook_t *next; + void (*fn)(ap_exception_info_t *); +} except_hook_t; + +static except_hook_t *except_hooks; + +static void except_hook_cleanup(void *ignored) +{ + except_hooks = NULL; +} + +API_EXPORT(int) ap_add_fatal_exception_hook(void (*fn)(ap_exception_info_t *)) +{ + except_hook_t *new; + + ap_assert(pconf); + + if (!ap_exception_hook_enabled) { + return 1; + } + + new = ap_palloc(pconf, sizeof(except_hook_t)); + new->next = except_hooks; + new->fn = fn; + except_hooks = new; + + return 0; +} + +static void run_fatal_exception_hook(int sig) +{ + except_hook_t *cur_hook = except_hooks; + ap_exception_info_t ei = {0}; + + if (ap_exception_hook_enabled && + geteuid() != 0) { + ei.sig = sig; + ei.pid = getpid(); + + while (cur_hook) { + cur_hook->fn(&ei); + cur_hook = cur_hook->next; + } + } +} +#endif /* AP_ENABLE_EXCEPTION_HOOK */ /* handle all varieties of core dumping signals */ static void sig_coredump(int sig) { chdir(ap_coredump_dir); signal(sig, SIG_DFL); +#ifdef AP_ENABLE_EXCEPTION_HOOK + run_fatal_exception_hook(sig); +#endif #if !defined(WIN32) && !defined(NETWARE) kill(getpid(), sig); #else @@ -4188,6 +4242,9 @@ static void common_init(void) pglobal = ap_init_alloc(); pconf = ap_make_sub_pool(pglobal); +#ifdef AP_ENABLE_EXCEPTION_HOOK + ap_register_cleanup(pconf, NULL, except_hook_cleanup, ap_null_cleanup); +#endif plog = ap_make_sub_pool(pglobal); ptrans = ap_make_sub_pool(pconf); @@ -5121,6 +5178,9 @@ static void standalone_main(int argc, char **argv) } #endif ap_clear_pool(pconf); +#ifdef AP_ENABLE_EXCEPTION_HOOK + ap_register_cleanup(pconf, NULL, except_hook_cleanup, ap_null_cleanup); +#endif ptrans = ap_make_sub_pool(pconf); ap_init_mutex_method(ap_default_mutex_method()); diff --git a/src/support/httpd.exp b/src/support/httpd.exp index fc01e8f333f..8ea7057c4ff 100644 --- a/src/support/httpd.exp +++ b/src/support/httpd.exp @@ -9,6 +9,7 @@ ap_SHA1Update_binary ap_SHA1Update ap_add_cgi_vars ap_add_common_vars +ap_add_fatal_exception_hook ap_add_file_conf ap_add_module ap_add_named_module