tmate-debug.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include <execinfo.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <regex.h>
  5. #include <signal.h>
  6. #include "tmate.h"
  7. #if DEBUG
  8. static int print_resolved_stack_frame(const char *frame)
  9. {
  10. char file[100];
  11. char cmd[200];
  12. char output[300];
  13. char address[20];
  14. char *line;
  15. FILE *ps;
  16. static regex_t _regex;
  17. static regex_t *regex;
  18. regmatch_t matches[3];
  19. if (!regex) {
  20. if (regcomp(&_regex, "(.+)\\(\\) \\[([^]]+)\\]", REG_EXTENDED))
  21. return -1;
  22. regex = &_regex;
  23. }
  24. if (regexec(regex, frame, 3, matches, 0))
  25. return -1;
  26. memcpy(file, &frame[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so);
  27. file[matches[1].rm_eo - matches[1].rm_so] = 0;
  28. memcpy(address, &frame[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so);
  29. address[matches[2].rm_eo - matches[2].rm_so] = 0;
  30. sprintf(cmd, "addr2line -e %s %s -f -p -s", file, address);
  31. ps = popen(cmd, "r");
  32. if (!ps)
  33. return -1;
  34. line = fgets(output, sizeof(output), ps);
  35. pclose(ps);
  36. if (!line)
  37. return -1;
  38. line[strlen(line)-1] = 0; /* remove \n */
  39. tmate_debug("%s(%s) [%s]", file, line, address);
  40. return 0;
  41. }
  42. #endif
  43. void tmate_print_stack_trace(void)
  44. {
  45. void *array[20];
  46. size_t size;
  47. char **strings;
  48. size_t i;
  49. size = backtrace (array, 20);
  50. strings = backtrace_symbols (array, size);
  51. tmate_info ("============ %zd stack frames ============", size);
  52. for (i = 1; i < size; i++) {
  53. #if DEBUG
  54. if (print_resolved_stack_frame(strings[i]) < 0)
  55. #endif
  56. tmate_info("%s", strings[i]);
  57. }
  58. free (strings);
  59. }
  60. static void handle_sigsegv(__unused int sig)
  61. {
  62. /* TODO send stack trace to server */
  63. tmate_info("CRASH, printing stack trace");
  64. tmate_print_stack_trace();
  65. tmate_fatal("CRASHED");
  66. }
  67. void tmate_catch_sigsegv(void)
  68. {
  69. signal(SIGSEGV, handle_sigsegv);
  70. }