PageRenderTime 38ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/third_party/glog/src/signalhandler.cc

http://github.com/tomahawk-player/tomahawk
C++ | 350 lines | 203 code | 36 blank | 111 comment | 24 complexity | 0348512354612e95608832dd69f98913 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-3.0, GPL-2.0
  1. // Copyright (c) 2008, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. //
  30. // Author: Satoru Takabayashi
  31. //
  32. // Implementation of InstallFailureSignalHandler().
  33. #include "utilities.h"
  34. #include "stacktrace.h"
  35. #include "symbolize.h"
  36. #include "glog/logging.h"
  37. #include <signal.h>
  38. #include <time.h>
  39. #ifdef HAVE_UCONTEXT_H
  40. # include <ucontext.h>
  41. #endif
  42. #ifdef HAVE_SYS_UCONTEXT_H
  43. # include <sys/ucontext.h>
  44. #endif
  45. #include <algorithm>
  46. _START_GOOGLE_NAMESPACE_
  47. namespace {
  48. // We'll install the failure signal handler for these signals. We could
  49. // use strsignal() to get signal names, but we don't use it to avoid
  50. // introducing yet another #ifdef complication.
  51. //
  52. // The list should be synced with the comment in signalhandler.h.
  53. const struct {
  54. int number;
  55. const char *name;
  56. } kFailureSignals[] = {
  57. { SIGSEGV, "SIGSEGV" },
  58. { SIGILL, "SIGILL" },
  59. { SIGFPE, "SIGFPE" },
  60. { SIGABRT, "SIGABRT" },
  61. { SIGBUS, "SIGBUS" },
  62. { SIGTERM, "SIGTERM" },
  63. };
  64. // Returns the program counter from signal context, NULL if unknown.
  65. void* GetPC(void* ucontext_in_void) {
  66. #if (defined(HAVE_UCONTEXT_H) || defined(HAVE_SYS_UCONTEXT_H)) && defined(PC_FROM_UCONTEXT)
  67. if (ucontext_in_void != NULL) {
  68. ucontext_t *context = reinterpret_cast<ucontext_t *>(ucontext_in_void);
  69. return (void*)context->PC_FROM_UCONTEXT;
  70. }
  71. #endif
  72. return NULL;
  73. }
  74. // The class is used for formatting error messages. We don't use printf()
  75. // as it's not async signal safe.
  76. class MinimalFormatter {
  77. public:
  78. MinimalFormatter(char *buffer, int size)
  79. : buffer_(buffer),
  80. cursor_(buffer),
  81. end_(buffer + size) {
  82. }
  83. // Returns the number of bytes written in the buffer.
  84. int num_bytes_written() const { return cursor_ - buffer_; }
  85. // Appends string from "str" and updates the internal cursor.
  86. void AppendString(const char* str) {
  87. int i = 0;
  88. while (str[i] != '\0' && cursor_ + i < end_) {
  89. cursor_[i] = str[i];
  90. ++i;
  91. }
  92. cursor_ += i;
  93. }
  94. // Formats "number" in "radix" and updates the internal cursor.
  95. // Lowercase letters are used for 'a' - 'z'.
  96. void AppendUint64(uint64 number, int radix) {
  97. int i = 0;
  98. while (cursor_ + i < end_) {
  99. const int tmp = number % radix;
  100. number /= radix;
  101. cursor_[i] = (tmp < 10 ? '0' + tmp : 'a' + tmp - 10);
  102. ++i;
  103. if (number == 0) {
  104. break;
  105. }
  106. }
  107. // Reverse the bytes written.
  108. std::reverse(cursor_, cursor_ + i);
  109. cursor_ += i;
  110. }
  111. // Formats "number" as hexadecimal number, and updates the internal
  112. // cursor. Padding will be added in front if needed.
  113. void AppendHexWithPadding(uint64 number, int width) {
  114. char* start = cursor_;
  115. AppendString("0x");
  116. AppendUint64(number, 16);
  117. // Move to right and add padding in front if needed.
  118. if (cursor_ < start + width) {
  119. const int64 delta = start + width - cursor_;
  120. std::copy(start, cursor_, start + delta);
  121. std::fill(start, start + delta, ' ');
  122. cursor_ = start + width;
  123. }
  124. }
  125. private:
  126. char *buffer_;
  127. char *cursor_;
  128. const char * const end_;
  129. };
  130. // Writes the given data with the size to the standard error.
  131. void WriteToStderr(const char* data, int size) {
  132. if (write(STDERR_FILENO, data, size) < 0) {
  133. // Ignore errors.
  134. }
  135. }
  136. // The writer function can be changed by InstallFailureWriter().
  137. void (*g_failure_writer)(const char* data, int size) = WriteToStderr;
  138. // Dumps time information. We don't dump human-readable time information
  139. // as localtime() is not guaranteed to be async signal safe.
  140. void DumpTimeInfo() {
  141. time_t time_in_sec = time(NULL);
  142. char buf[256]; // Big enough for time info.
  143. MinimalFormatter formatter(buf, sizeof(buf));
  144. formatter.AppendString("*** Aborted at ");
  145. formatter.AppendUint64(time_in_sec, 10);
  146. formatter.AppendString(" (unix time)");
  147. formatter.AppendString(" try \"date -d @");
  148. formatter.AppendUint64(time_in_sec, 10);
  149. formatter.AppendString("\" if you are using GNU date ***\n");
  150. g_failure_writer(buf, formatter.num_bytes_written());
  151. }
  152. // Dumps information about the signal to STDERR.
  153. void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
  154. // Get the signal name.
  155. const char* signal_name = NULL;
  156. for (int i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
  157. if (signal_number == kFailureSignals[i].number) {
  158. signal_name = kFailureSignals[i].name;
  159. }
  160. }
  161. char buf[256]; // Big enough for signal info.
  162. MinimalFormatter formatter(buf, sizeof(buf));
  163. formatter.AppendString("*** ");
  164. if (signal_name) {
  165. formatter.AppendString(signal_name);
  166. } else {
  167. // Use the signal number if the name is unknown. The signal name
  168. // should be known, but just in case.
  169. formatter.AppendString("Signal ");
  170. formatter.AppendUint64(signal_number, 10);
  171. }
  172. formatter.AppendString(" (@0x");
  173. formatter.AppendUint64(reinterpret_cast<uintptr_t>(siginfo->si_addr), 16);
  174. formatter.AppendString(")");
  175. formatter.AppendString(" received by PID ");
  176. formatter.AppendUint64(getpid(), 10);
  177. formatter.AppendString(" (TID 0x");
  178. // We assume pthread_t is an integral number or a pointer, rather
  179. // than a complex struct. In some environments, pthread_self()
  180. // returns an uint64 but in some other environments pthread_self()
  181. // returns a pointer. Hence we use C-style cast here, rather than
  182. // reinterpret/static_cast, to support both types of environments.
  183. formatter.AppendUint64((uintptr_t)pthread_self(), 16);
  184. formatter.AppendString(") ");
  185. // Only linux has the PID of the signal sender in si_pid.
  186. #ifdef OS_LINUX
  187. formatter.AppendString("from PID ");
  188. formatter.AppendUint64(siginfo->si_pid, 10);
  189. formatter.AppendString("; ");
  190. #endif
  191. formatter.AppendString("stack trace: ***\n");
  192. g_failure_writer(buf, formatter.num_bytes_written());
  193. }
  194. // Dumps information about the stack frame to STDERR.
  195. void DumpStackFrameInfo(const char* prefix, void* pc) {
  196. // Get the symbol name.
  197. const char *symbol = "(unknown)";
  198. char symbolized[1024]; // Big enough for a sane symbol.
  199. // Symbolizes the previous address of pc because pc may be in the
  200. // next function.
  201. if (Symbolize(reinterpret_cast<char *>(pc) - 1,
  202. symbolized, sizeof(symbolized))) {
  203. symbol = symbolized;
  204. }
  205. char buf[1024]; // Big enough for stack frame info.
  206. MinimalFormatter formatter(buf, sizeof(buf));
  207. formatter.AppendString(prefix);
  208. formatter.AppendString("@ ");
  209. const int width = 2 * sizeof(void*) + 2; // + 2 for "0x".
  210. formatter.AppendHexWithPadding(reinterpret_cast<uintptr_t>(pc), width);
  211. formatter.AppendString(" ");
  212. formatter.AppendString(symbol);
  213. formatter.AppendString("\n");
  214. g_failure_writer(buf, formatter.num_bytes_written());
  215. }
  216. // Invoke the default signal handler.
  217. void InvokeDefaultSignalHandler(int signal_number) {
  218. struct sigaction sig_action;
  219. memset(&sig_action, 0, sizeof(sig_action));
  220. sigemptyset(&sig_action.sa_mask);
  221. sig_action.sa_handler = SIG_DFL;
  222. sigaction(signal_number, &sig_action, NULL);
  223. kill(getpid(), signal_number);
  224. }
  225. // This variable is used for protecting FailureSignalHandler() from
  226. // dumping stuff while another thread is doing it. Our policy is to let
  227. // the first thread dump stuff and let other threads wait.
  228. // See also comments in FailureSignalHandler().
  229. static pthread_t* g_entered_thread_id_pointer = NULL;
  230. // Dumps signal and stack frame information, and invokes the default
  231. // signal handler once our job is done.
  232. void FailureSignalHandler(int signal_number,
  233. siginfo_t *signal_info,
  234. void *ucontext) {
  235. // First check if we've already entered the function. We use an atomic
  236. // compare and swap operation for platforms that support it. For other
  237. // platforms, we use a naive method that could lead to a subtle race.
  238. // We assume pthread_self() is async signal safe, though it's not
  239. // officially guaranteed.
  240. pthread_t my_thread_id = pthread_self();
  241. // NOTE: We could simply use pthread_t rather than pthread_t* for this,
  242. // if pthread_self() is guaranteed to return non-zero value for thread
  243. // ids, but there is no such guarantee. We need to distinguish if the
  244. // old value (value returned from __sync_val_compare_and_swap) is
  245. // different from the original value (in this case NULL).
  246. pthread_t* old_thread_id_pointer =
  247. glog_internal_namespace_::sync_val_compare_and_swap(
  248. &g_entered_thread_id_pointer,
  249. static_cast<pthread_t*>(NULL),
  250. &my_thread_id);
  251. if (old_thread_id_pointer != NULL) {
  252. // We've already entered the signal handler. What should we do?
  253. if (pthread_equal(my_thread_id, *g_entered_thread_id_pointer)) {
  254. // It looks the current thread is reentering the signal handler.
  255. // Something must be going wrong (maybe we are reentering by another
  256. // type of signal?). Kill ourself by the default signal handler.
  257. InvokeDefaultSignalHandler(signal_number);
  258. }
  259. // Another thread is dumping stuff. Let's wait until that thread
  260. // finishes the job and kills the process.
  261. while (true) {
  262. sleep(1);
  263. }
  264. }
  265. // This is the first time we enter the signal handler. We are going to
  266. // do some interesting stuff from here.
  267. // TODO(satorux): We might want to set timeout here using alarm(), but
  268. // mixing alarm() and sleep() can be a bad idea.
  269. // First dump time info.
  270. DumpTimeInfo();
  271. // Get the program counter from ucontext.
  272. void *pc = GetPC(ucontext);
  273. DumpStackFrameInfo("PC: ", pc);
  274. #ifdef HAVE_STACKTRACE
  275. // Get the stack traces.
  276. void *stack[32];
  277. // +1 to exclude this function.
  278. const int depth = GetStackTrace(stack, ARRAYSIZE(stack), 1);
  279. DumpSignalInfo(signal_number, signal_info);
  280. // Dump the stack traces.
  281. for (int i = 0; i < depth; ++i) {
  282. DumpStackFrameInfo(" ", stack[i]);
  283. }
  284. #endif
  285. // *** TRANSITION ***
  286. //
  287. // BEFORE this point, all code must be async-termination-safe!
  288. // (See WARNING above.)
  289. //
  290. // AFTER this point, we do unsafe things, like using LOG()!
  291. // The process could be terminated or hung at any time. We try to
  292. // do more useful things first and riskier things later.
  293. // Flush the logs before we do anything in case 'anything'
  294. // causes problems.
  295. FlushLogFilesUnsafe(0);
  296. // Kill ourself by the default signal handler.
  297. InvokeDefaultSignalHandler(signal_number);
  298. }
  299. } // namespace
  300. void InstallFailureSignalHandler() {
  301. // Build the sigaction struct.
  302. struct sigaction sig_action;
  303. memset(&sig_action, 0, sizeof(sig_action));
  304. sigemptyset(&sig_action.sa_mask);
  305. sig_action.sa_flags |= SA_SIGINFO;
  306. sig_action.sa_sigaction = &FailureSignalHandler;
  307. for (int i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
  308. CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
  309. }
  310. }
  311. void InstallFailureWriter(void (*writer)(const char* data, int size)) {
  312. g_failure_writer = writer;
  313. }
  314. _END_GOOGLE_NAMESPACE_