diff options
Diffstat (limited to 'APACHE_1_3_42/src/modules/experimental/mod_backtrace.c')
-rw-r--r-- | APACHE_1_3_42/src/modules/experimental/mod_backtrace.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/APACHE_1_3_42/src/modules/experimental/mod_backtrace.c b/APACHE_1_3_42/src/modules/experimental/mod_backtrace.c new file mode 100644 index 0000000000..fc61773957 --- /dev/null +++ b/APACHE_1_3_42/src/modules/experimental/mod_backtrace.c @@ -0,0 +1,204 @@ +/* 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. + */ + +#if !defined(__linux__) && !defined(__FreeBSD__) +#error This module is currently only implemented for Linux and FreeBSD. +#endif + +/* + * Documentation: + * + * mod_backtrace is an experimental module for Apache httpd 1.3 which + * collects backtraces when a child process crashes. Currently it is + * implemented only on Linux and FreeBSD, but other platforms could be + * supported in the future. You should verify that it works reasonably + * on your system before putting it in production. + * + * It implements a fatal exception hook that will be called when a child + * process crashes. In the exception hook it uses system library routines + * to obtain information about the call stack, and it writes the call + * stack to a log file or the web server error log. The backtrace is a + * critical piece of information when determining the failing software + * component that caused the crash. Note that the backtrace written by + * mod_backtrace may not have as much information as a debugger can + * display from a core dump. + * + * Apache httpd requirements for mod_backtrace: + * + * Apache httpd >= 1.3.30 must be built with the AP_ENABLE_EXCEPTION_HOOK + * symbol defined and mod_so enabled. AP_ENABLE_EXCEPTION_HOOK is already + * defined in ap_config.h for some platforms, including AIX, Linux, + * Solaris, and HP-UX. It can be enabled for other platforms by including + * -DAP_ENABLE_EXCEPTION_HOOK in CFLAGS when the configure script is + * invoked. + * + * Compiling mod_backtrace: + * + * Linux: + * apxs -ci mod_backtrace.c + * + * FreeBSD: + * install libexecinfo from the Ports system then + * apxs -ci -L/usr/local/lib -lexecinfo mod_backtrace.c + * + * Activating mod_backtrace: + * + * 1. Load it like any other DSO: + * LoadModule backtrace_module libexec/mod_backtrace.so + * ... + * AddModule mod_backtrace.c + * + * 2. Enable exception hooks for modules like mod_backtrace: + * EnableExceptionHook On + * + * 3. Choose where backtrace information should be written. + * If you want backtraces from crashes to be reported some place other + * than the error log, use the BacktraceLog directive to specify a + * fully-qualified filename for the log to which backtraces will be + * written. Note that the web server user id (e.g., "nobody") must + * be able to create or append to this log file, as the log file is + * not opened until a crash occurs. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" + +#include <fcntl.h> +#include <unistd.h> +#include <execinfo.h> + +static char *log_fname; + +static void bt_show_backtrace(int sig) +{ + char msgbuf[128]; + size_t size; + void *array[20]; + extern int main(); + int logfd; + time_t now; + char msg_prefix[60]; + char *newline; + int using_errorlog = 1; + + time(&now); + ap_snprintf(msg_prefix, sizeof msg_prefix, + "[%s pid %ld mod_backtrace", + asctime(localtime(&now)), + (long)getpid()); + newline = strchr(msg_prefix, '\n'); /* dang asctime() */ + if (newline) { /* silly we are */ + *newline = ']'; + } + + if (log_fname) { + logfd = open(log_fname, O_WRONLY|O_APPEND|O_CREAT, 0644); + if (logfd == -1) { + logfd = 2; /* unix, so fd 2 is the web server error log */ + ap_snprintf(msgbuf, sizeof msgbuf, + "%s error %d opening %s\n", + msg_prefix, errno, log_fname); + write(logfd, msgbuf, strlen(msgbuf)); + } + else { + using_errorlog = 0; + } + } + else { + logfd = 2; + } + + ap_snprintf(msgbuf, sizeof msgbuf, + "%s backtrace for signal %d\n", + msg_prefix, sig); + write(logfd, msgbuf, strlen(msgbuf)); + + /* the address of main() can be useful if we're on old + * glibc and get only addresses for stack frames... knowing + * where main() is then is a useful clue + */ + ap_snprintf(msgbuf, sizeof msgbuf, + "%s main() is at %pp\n", + msg_prefix, + main);/* don't you DARE put parens after "main" */ + write(logfd, msgbuf, strlen(msgbuf)); + + size = backtrace(array, sizeof array / sizeof array[0]); + backtrace_symbols_fd(array, size, logfd); + ap_snprintf(msgbuf, sizeof msgbuf, + "%s end of report\n", + msg_prefix); + write(logfd, msgbuf, strlen(msgbuf)); + if (!using_errorlog) { + close(logfd); + } +} + +static void bt_exception_hook(ap_exception_info_t *ei) +{ + bt_show_backtrace(ei->sig); +} + +static void bt_init(server_rec *s, pool *p) +{ + int rc = ap_add_fatal_exception_hook(bt_exception_hook); + + if (rc) { + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s, + "fatal exception hooks are not enabled; please " + "enable them with the EnableExceptionHook directive " + "or disable mod_backtrace"); + } +} + +static const char *bt_cmd_file(cmd_parms *cmd, void *dconf, char *fname) +{ + log_fname = ap_pstrdup(cmd->pool, fname); + return NULL; +} + +static const command_rec bt_command_table[] = { + { + "BacktraceLog", bt_cmd_file, NULL, RSRC_CONF, TAKE1, "the fully-qualified filename of the mod_backtrace logfile" + } + , + { + NULL + } +}; + +module MODULE_VAR_EXPORT backtrace_module = { + STANDARD_MODULE_STUFF, + bt_init, /* initializer */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + NULL, /* server config */ + NULL, /* merge server config */ + bt_command_table, /* command table */ + NULL, /* handlers */ + NULL, /* filename translation */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + NULL, /* fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child init */ + NULL, /* child exit */ + NULL /* post read request */ +}; |