|
@@ -0,0 +1,157 @@
|
|
|
+/* 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);
|
|
|
+}
|
|
|
+
|