123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /* Copyright (c) 2013, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #include "orconfig.h"
- #include "backtrace.h"
- #include "compat.h"
- #include "util.h"
- #ifdef HAVE_EXECINFO_H
- #include <execinfo.h>
- #endif
- #ifdef HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
- defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
- #define USE_BACKTRACE
- #endif
- #if !defined(USE_BACKTRACE)
- #define NO_BACKTRACE_IMPL
- #endif
- static char *bt_filename = NULL;
- static char *bt_version = NULL;
- #ifndef NO_BACKTRACE_IMPL
- /**DOCDOC*/
- static int
- open_bt_target(void)
- {
- int fd = -1;
- if (bt_filename)
- fd = open(bt_filename, O_WRONLY|O_CREAT|O_APPEND, 0700);
- return fd;
- }
- #endif
- /**DOCDOC*/
- static void
- bt_write(int fd, const char *s, ssize_t n)
- {
- int r;
- if (n < 0) n = strlen(s);
- r = write(STDERR_FILENO, s, n);
- if (fd >= 0)
- r = write(fd, s, n);
- (void)r;
- }
- #ifdef USE_BACKTRACE
- #define MAX_DEPTH 256
- static void *cb_buf[MAX_DEPTH];
- /**DOCDOC*/
- void
- dump_backtrace(const char *msg)
- {
- char timebuf[32];
- time_t t = time(NULL);
- int timebuf_len;
- int depth;
- int fd;
- if (!msg) msg = "unspecified crash";
- depth = backtrace(cb_buf, MAX_DEPTH);
- t /= 900; t *= 900; /* Round to the previous 15 minutes */
- timebuf[0] = '\0';
- timebuf_len = format_dec_number_sigsafe(t, timebuf, sizeof(timebuf));
- fd = open_bt_target();
- bt_write(fd, "========================================"
- "====================================\n", -1);
- bt_write(fd, bt_version, -1);
- bt_write(fd, " died around T=", -1);
- bt_write(fd, timebuf, timebuf_len);
- bt_write(fd, ": ", 2);
- bt_write(fd, msg, -1);
- bt_write(fd, "\n", 1);
- backtrace_symbols_fd(cb_buf, depth, STDERR_FILENO);
- if (fd >= 0)
- backtrace_symbols_fd(cb_buf, depth, fd);
- close(fd);
- }
- /**DOCDOC*/
- static int
- install_bt_handler(void)
- {
- /*XXXX add signal handlers */
- /*XXXX make this idempotent */
- return 0;
- }
- /**DOCDOC*/
- static void
- remove_bt_handler(void)
- {
- }
- #endif
- #ifdef NO_BACKTRACE_IMPL
- /**DOCDOC*/
- void
- dump_backtrace(const char *msg)
- {
- bt_write(-1, bt_version, -1);
- bt_write(-1, " died: ", -1);
- bt_write(-1, msg, -1);
- bt_write(-1, "\n", -1);
- }
- /**DOCDOC*/
- static int
- install_bt_handler(void)
- {
- return 0;
- }
- /**DOCDOC*/
- static void
- remove_bt_handler(void)
- {
- }
- #endif
- /**DOCDOC*/
- int
- configure_backtrace_handler(const char *filename, const char *tor_version)
- {
- tor_free(bt_filename);
- if (filename)
- bt_filename = tor_strdup(filename);
- tor_free(bt_version);
- if (!tor_version)
- tor_version = "Tor";
- bt_version = tor_strdup(tor_version);
- return install_bt_handler();
- }
- /**DOCDOC*/
- void
- clean_up_backtrace_handler(void)
- {
- remove_bt_handler();
- tor_free(bt_filename);
- tor_free(bt_version);
- }
|