Index: src/include/ap_config.h =================================================================== RCS file: /home/cvs/apache-1.3/src/include/ap_config.h,v retrieving revision 1.331 diff -u -r1.331 ap_config.h --- src/include/ap_config.h 1 Jan 2004 13:32:53 -0000 1.331 +++ src/include/ap_config.h 24 Jan 2004 12:12:03 -0000 @@ -193,6 +193,7 @@ 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 @@ #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 @@ #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 Index: src/include/http_conf_globals.h =================================================================== RCS file: /home/cvs/apache-1.3/src/include/http_conf_globals.h,v retrieving revision 1.53 diff -u -r1.53 http_conf_globals.h --- src/include/http_conf_globals.h 1 Jan 2004 13:32:53 -0000 1.53 +++ src/include/http_conf_globals.h 24 Jan 2004 12:12:03 -0000 @@ -100,6 +100,9 @@ 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; Index: src/include/httpd.h =================================================================== RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.375 diff -u -r1.375 httpd.h --- src/include/httpd.h 1 Jan 2004 13:32:53 -0000 1.375 +++ src/include/httpd.h 24 Jan 2004 12:12:04 -0000 @@ -1226,6 +1226,32 @@ #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 server may not recover 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 Index: src/main/http_core.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v retrieving revision 1.328 diff -u -r1.328 http_core.c --- src/main/http_core.c 1 Jan 2004 13:32:54 -0000 1.328 +++ src/main/http_core.c 24 Jan 2004 12:12:07 -0000 @@ -2248,6 +2248,32 @@ 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 @@ #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 Index: src/main/http_main.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v retrieving revision 1.607 diff -u -r1.607 http_main.c --- src/main/http_main.c 13 Jan 2004 19:09:40 -0000 1.607 +++ src/main/http_main.c 24 Jan 2004 12:12:12 -0000 @@ -260,6 +260,9 @@ 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 @@ } #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 @@ 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 @@ } #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()); Index: src/support/httpd.exp =================================================================== RCS file: /home/cvs/apache-1.3/src/support/httpd.exp,v retrieving revision 1.41 diff -u -r1.41 httpd.exp --- src/support/httpd.exp 17 Jan 2003 12:23:10 -0000 1.41 +++ src/support/httpd.exp 24 Jan 2004 12:12:14 -0000 @@ -9,6 +9,7 @@ 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