system.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include <stdarg.h>
  2. #include <stdio.h>
  3. #include <sys/stat.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <AP_HAL/AP_HAL.h>
  8. #include <AP_HAL/system.h>
  9. #include "Scheduler.h"
  10. extern const AP_HAL::HAL& hal;
  11. using HALSITL::Scheduler;
  12. namespace AP_HAL {
  13. static struct {
  14. struct timeval start_time;
  15. } state;
  16. void init()
  17. {
  18. gettimeofday(&state.start_time, nullptr);
  19. }
  20. void panic(const char *errormsg, ...)
  21. {
  22. va_list ap;
  23. fflush(stdout);
  24. va_start(ap, errormsg);
  25. vprintf(errormsg, ap);
  26. va_end(ap);
  27. printf("\n");
  28. dump_stack_trace();
  29. if (getenv("SITL_PANIC_EXIT")) {
  30. // this is used on the autotest server to prevent us waiting
  31. // 10 hours for a timeout
  32. exit(1);
  33. }
  34. for(;;);
  35. }
  36. // partly flogged from: https://github.com/tridge/junkcode/blob/master/segv_handler/segv_handler.c
  37. void dump_stack_trace()
  38. {
  39. // find dumpstack command:
  40. const char *dumpstack = "dumpstack"; // if we can't find it trust in PATH
  41. struct stat statbuf;
  42. const char *paths[] {
  43. "Tools/scripts/dumpstack",
  44. "APM/Tools/scripts/dumpstack", // for autotest server
  45. };
  46. for (uint8_t i=0; i<ARRAY_SIZE(paths); i++) {
  47. if (::stat(paths[i], &statbuf) != -1) {
  48. dumpstack = paths[i];
  49. break;
  50. }
  51. }
  52. char cmd[100];
  53. char progname[100];
  54. char *p;
  55. int n;
  56. n = readlink("/proc/self/exe", progname, sizeof(progname)-1);
  57. if (n == -1) {
  58. strncpy(progname, "unknown", sizeof(progname));
  59. n = strlen(progname);
  60. }
  61. progname[n] = 0;
  62. p = strrchr(progname, '/');
  63. *p = 0;
  64. char output_filepath[30];
  65. snprintf(output_filepath,
  66. ARRAY_SIZE(output_filepath),
  67. "segv_%s.%d.out",
  68. p+1,
  69. (int)getpid());
  70. snprintf(cmd,
  71. sizeof(cmd),
  72. "sh %s %d >%s 2>&1",
  73. dumpstack,
  74. (int)getpid(),
  75. output_filepath);
  76. fprintf(stderr, "Running: %s\n", cmd);
  77. if (system(cmd)) {
  78. fprintf(stderr, "Failed\n");
  79. return;
  80. }
  81. fprintf(stderr, "Stack dumped\n");
  82. // print the trace on stderr:
  83. int fd = open(output_filepath, O_RDONLY);
  84. if (fd == -1) {
  85. fprintf(stderr, "Failed to open stack dump filepath: %m");
  86. return;
  87. }
  88. char buf[1024]; // let's hope we're not here because we ran out of stack
  89. while (true) {
  90. const ssize_t ret = read(fd, buf, ARRAY_SIZE(buf));
  91. if (ret == -1) {
  92. fprintf(stderr, "Read error: %m");
  93. break;
  94. }
  95. if (ret == 0) {
  96. break;
  97. }
  98. if (write(2, buf, ret) != ret) {
  99. // *sigh*
  100. break;
  101. }
  102. }
  103. close(fd);
  104. }
  105. uint32_t micros()
  106. {
  107. return micros64() & 0xFFFFFFFF;
  108. }
  109. uint32_t millis()
  110. {
  111. return millis64() & 0xFFFFFFFF;
  112. }
  113. /*
  114. we define a millis16() here to avoid an issue with sitl builds in cygwin
  115. */
  116. uint16_t millis16()
  117. {
  118. return millis64() & 0xFFFF;
  119. }
  120. uint64_t micros64()
  121. {
  122. const HALSITL::Scheduler* scheduler = HALSITL::Scheduler::from(hal.scheduler);
  123. uint64_t stopped_usec = scheduler->stopped_clock_usec();
  124. if (stopped_usec) {
  125. return stopped_usec;
  126. }
  127. struct timeval tp;
  128. gettimeofday(&tp, nullptr);
  129. uint64_t ret = 1.0e6 * ((tp.tv_sec + (tp.tv_usec * 1.0e-6)) -
  130. (state.start_time.tv_sec +
  131. (state.start_time.tv_usec * 1.0e-6)));
  132. return ret;
  133. }
  134. uint64_t millis64()
  135. {
  136. const HALSITL::Scheduler* scheduler = HALSITL::Scheduler::from(hal.scheduler);
  137. uint64_t stopped_usec = scheduler->stopped_clock_usec();
  138. if (stopped_usec) {
  139. return stopped_usec / 1000;
  140. }
  141. struct timeval tp;
  142. gettimeofday(&tp, nullptr);
  143. uint64_t ret = 1.0e3*((tp.tv_sec + (tp.tv_usec*1.0e-6)) -
  144. (state.start_time.tv_sec +
  145. (state.start_time.tv_usec*1.0e-6)));
  146. return ret;
  147. }
  148. } // namespace AP_HAL