backtrace.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* Copyright (c) 2013, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #include "backtrace.h"
  5. #include "compat.h"
  6. #include "util.h"
  7. #ifdef HAVE_EXECINFO_H
  8. #include <execinfo.h>
  9. #endif
  10. #ifdef HAVE_FCNTL_H
  11. #include <fcntl.h>
  12. #endif
  13. #ifdef HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
  17. defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
  18. #define USE_BACKTRACE
  19. #endif
  20. #if !defined(USE_BACKTRACE)
  21. #define NO_BACKTRACE_IMPL
  22. #endif
  23. static char *bt_filename = NULL;
  24. static char *bt_version = NULL;
  25. #ifndef NO_BACKTRACE_IMPL
  26. /**DOCDOC*/
  27. static int
  28. open_bt_target(void)
  29. {
  30. int fd = -1;
  31. if (bt_filename)
  32. fd = open(bt_filename, O_WRONLY|O_CREAT|O_APPEND, 0700);
  33. return fd;
  34. }
  35. #endif
  36. /**DOCDOC*/
  37. static void
  38. bt_write(int fd, const char *s, ssize_t n)
  39. {
  40. int r;
  41. if (n < 0) n = strlen(s);
  42. r = write(STDERR_FILENO, s, n);
  43. if (fd >= 0)
  44. r = write(fd, s, n);
  45. (void)r;
  46. }
  47. #ifdef USE_BACKTRACE
  48. #define MAX_DEPTH 256
  49. static void *cb_buf[MAX_DEPTH];
  50. /**DOCDOC*/
  51. void
  52. dump_backtrace(const char *msg)
  53. {
  54. char timebuf[32];
  55. time_t t = time(NULL);
  56. int timebuf_len;
  57. int depth;
  58. int fd;
  59. if (!msg) msg = "unspecified crash";
  60. depth = backtrace(cb_buf, MAX_DEPTH);
  61. t /= 900; t *= 900; /* Round to the previous 15 minutes */
  62. timebuf[0] = '\0';
  63. timebuf_len = format_dec_number_sigsafe(t, timebuf, sizeof(timebuf));
  64. fd = open_bt_target();
  65. bt_write(fd, "========================================"
  66. "====================================\n", -1);
  67. bt_write(fd, bt_version, -1);
  68. bt_write(fd, " died around T=", -1);
  69. bt_write(fd, timebuf, timebuf_len);
  70. bt_write(fd, ": ", 2);
  71. bt_write(fd, msg, -1);
  72. bt_write(fd, "\n", 1);
  73. backtrace_symbols_fd(cb_buf, depth, STDERR_FILENO);
  74. if (fd >= 0)
  75. backtrace_symbols_fd(cb_buf, depth, fd);
  76. close(fd);
  77. }
  78. /**DOCDOC*/
  79. static int
  80. install_bt_handler(void)
  81. {
  82. /*XXXX add signal handlers */
  83. /*XXXX make this idempotent */
  84. return 0;
  85. }
  86. /**DOCDOC*/
  87. static void
  88. remove_bt_handler(void)
  89. {
  90. }
  91. #endif
  92. #ifdef NO_BACKTRACE_IMPL
  93. /**DOCDOC*/
  94. void
  95. dump_backtrace(const char *msg)
  96. {
  97. bt_write(-1, bt_version, -1);
  98. bt_write(-1, " died: ", -1);
  99. bt_write(-1, msg, -1);
  100. bt_write(-1, "\n", -1);
  101. }
  102. /**DOCDOC*/
  103. static int
  104. install_bt_handler(void)
  105. {
  106. return 0;
  107. }
  108. /**DOCDOC*/
  109. static void
  110. remove_bt_handler(void)
  111. {
  112. }
  113. #endif
  114. /**DOCDOC*/
  115. int
  116. configure_backtrace_handler(const char *filename, const char *tor_version)
  117. {
  118. tor_free(bt_filename);
  119. if (filename)
  120. bt_filename = tor_strdup(filename);
  121. tor_free(bt_version);
  122. if (!tor_version)
  123. tor_version = "Tor";
  124. bt_version = tor_strdup(tor_version);
  125. return install_bt_handler();
  126. }
  127. /**DOCDOC*/
  128. void
  129. clean_up_backtrace_handler(void)
  130. {
  131. remove_bt_handler();
  132. tor_free(bt_filename);
  133. tor_free(bt_version);
  134. }