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

http://github.com/tomahawk-player/tomahawk · C++ · 346 lines · 234 code · 51 blank · 61 comment · 25 complexity · 423caa7488948002bb742d14a8097dce MD5 · raw file

  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: Shinichiro Hamaji
  31. #include "utilities.h"
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <signal.h>
  35. #ifdef HAVE_SYS_TIME_H
  36. # include <sys/time.h>
  37. #endif
  38. #include <time.h>
  39. #if defined(HAVE_SYSCALL_H)
  40. #include <syscall.h> // for syscall()
  41. #elif defined(HAVE_SYS_SYSCALL_H)
  42. #include <sys/syscall.h> // for syscall()
  43. #endif
  44. #ifdef HAVE_SYSLOG_H
  45. # include <syslog.h>
  46. #endif
  47. #include "base/googleinit.h"
  48. using std::string;
  49. _START_GOOGLE_NAMESPACE_
  50. static const char* g_program_invocation_short_name = NULL;
  51. static pthread_t g_main_thread_id;
  52. _END_GOOGLE_NAMESPACE_
  53. // The following APIs are all internal.
  54. #ifdef HAVE_STACKTRACE
  55. #include "stacktrace.h"
  56. #include "symbolize.h"
  57. #include "base/commandlineflags.h"
  58. GLOG_DEFINE_bool(symbolize_stacktrace, true,
  59. "Symbolize the stack trace in the tombstone");
  60. _START_GOOGLE_NAMESPACE_
  61. typedef void DebugWriter(const char*, void*);
  62. // The %p field width for printf() functions is two characters per byte.
  63. // For some environments, add two extra bytes for the leading "0x".
  64. static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
  65. static void DebugWriteToStderr(const char* data, void *unused) {
  66. // This one is signal-safe.
  67. if (write(STDERR_FILENO, data, strlen(data)) < 0) {
  68. // Ignore errors.
  69. }
  70. }
  71. void DebugWriteToString(const char* data, void *arg) {
  72. reinterpret_cast<string*>(arg)->append(data);
  73. }
  74. #ifdef HAVE_SYMBOLIZE
  75. // Print a program counter and its symbol name.
  76. static void DumpPCAndSymbol(DebugWriter *writerfn, void *arg, void *pc,
  77. const char * const prefix) {
  78. char tmp[1024];
  79. const char *symbol = "(unknown)";
  80. // Symbolizes the previous address of pc because pc may be in the
  81. // next function. The overrun happens when the function ends with
  82. // a call to a function annotated noreturn (e.g. CHECK).
  83. if (Symbolize(reinterpret_cast<char *>(pc) - 1, tmp, sizeof(tmp))) {
  84. symbol = tmp;
  85. }
  86. char buf[1024];
  87. snprintf(buf, sizeof(buf), "%s@ %*p %s\n",
  88. prefix, kPrintfPointerFieldWidth, pc, symbol);
  89. writerfn(buf, arg);
  90. }
  91. #endif
  92. static void DumpPC(DebugWriter *writerfn, void *arg, void *pc,
  93. const char * const prefix) {
  94. char buf[100];
  95. snprintf(buf, sizeof(buf), "%s@ %*p\n",
  96. prefix, kPrintfPointerFieldWidth, pc);
  97. writerfn(buf, arg);
  98. }
  99. // Dump current stack trace as directed by writerfn
  100. static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg) {
  101. // Print stack trace
  102. void* stack[32];
  103. int depth = GetStackTrace(stack, ARRAYSIZE(stack), skip_count+1);
  104. for (int i = 0; i < depth; i++) {
  105. #if defined(HAVE_SYMBOLIZE)
  106. if (FLAGS_symbolize_stacktrace) {
  107. DumpPCAndSymbol(writerfn, arg, stack[i], " ");
  108. } else {
  109. DumpPC(writerfn, arg, stack[i], " ");
  110. }
  111. #else
  112. DumpPC(writerfn, arg, stack[i], " ");
  113. #endif
  114. }
  115. }
  116. static void DumpStackTraceAndExit() {
  117. DumpStackTrace(1, DebugWriteToStderr, NULL);
  118. // Set the default signal handler for SIGABRT, to avoid invoking our
  119. // own signal handler installed by InstallFailedSignalHandler().
  120. struct sigaction sig_action;
  121. memset(&sig_action, 0, sizeof(sig_action));
  122. sigemptyset(&sig_action.sa_mask);
  123. sig_action.sa_handler = SIG_DFL;
  124. sigaction(SIGABRT, &sig_action, NULL);
  125. abort();
  126. }
  127. _END_GOOGLE_NAMESPACE_
  128. #endif // HAVE_STACKTRACE
  129. _START_GOOGLE_NAMESPACE_
  130. namespace glog_internal_namespace_ {
  131. const char* ProgramInvocationShortName() {
  132. if (g_program_invocation_short_name != NULL) {
  133. return g_program_invocation_short_name;
  134. } else {
  135. // TODO(hamaji): Use /proc/self/cmdline and so?
  136. return "UNKNOWN";
  137. }
  138. }
  139. bool IsGoogleLoggingInitialized() {
  140. return g_program_invocation_short_name != NULL;
  141. }
  142. bool is_default_thread() {
  143. if (g_program_invocation_short_name == NULL) {
  144. // InitGoogleLogging() not yet called, so unlikely to be in a different
  145. // thread
  146. return true;
  147. } else {
  148. return pthread_equal(pthread_self(), g_main_thread_id);
  149. }
  150. }
  151. #ifdef OS_WINDOWS
  152. struct timeval {
  153. long tv_sec, tv_usec;
  154. };
  155. // Based on: http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/os_win32.c&q=GetSystemTimeAsFileTime%20license:bsd
  156. // See COPYING for copyright information.
  157. static int gettimeofday(struct timeval *tv, void* tz) {
  158. #define EPOCHFILETIME (116444736000000000ULL)
  159. FILETIME ft;
  160. LARGE_INTEGER li;
  161. uint64 tt;
  162. GetSystemTimeAsFileTime(&ft);
  163. li.LowPart = ft.dwLowDateTime;
  164. li.HighPart = ft.dwHighDateTime;
  165. tt = (li.QuadPart - EPOCHFILETIME) / 10;
  166. tv->tv_sec = tt / 1000000;
  167. tv->tv_usec = tt % 1000000;
  168. return 0;
  169. }
  170. #endif
  171. int64 CycleClock_Now() {
  172. // TODO(hamaji): temporary impementation - it might be too slow.
  173. struct timeval tv;
  174. gettimeofday(&tv, NULL);
  175. return static_cast<int64>(tv.tv_sec) * 1000000 + tv.tv_usec;
  176. }
  177. int64 UsecToCycles(int64 usec) {
  178. return usec;
  179. }
  180. WallTime WallTime_Now() {
  181. // Now, cycle clock is retuning microseconds since the epoch.
  182. return CycleClock_Now() * 0.000001;
  183. }
  184. static int32 g_main_thread_pid = getpid();
  185. int32 GetMainThreadPid() {
  186. return g_main_thread_pid;
  187. }
  188. bool PidHasChanged() {
  189. int32 pid = getpid();
  190. if (g_main_thread_pid == pid) {
  191. return false;
  192. }
  193. g_main_thread_pid = pid;
  194. return true;
  195. }
  196. pid_t GetTID() {
  197. // On Linux and FreeBSD, we try to use gettid().
  198. #if defined OS_LINUX || defined OS_FREEBSD || defined OS_MACOSX
  199. #ifndef __NR_gettid
  200. #ifdef OS_MACOSX
  201. #define __NR_gettid SYS_gettid
  202. #elif ! defined __i386__
  203. #error "Must define __NR_gettid for non-x86 platforms"
  204. #else
  205. #define __NR_gettid 224
  206. #endif
  207. #endif
  208. static bool lacks_gettid = false;
  209. if (!lacks_gettid) {
  210. pid_t tid = syscall(__NR_gettid);
  211. if (tid != -1) {
  212. return tid;
  213. }
  214. // Technically, this variable has to be volatile, but there is a small
  215. // performance penalty in accessing volatile variables and there should
  216. // not be any serious adverse effect if a thread does not immediately see
  217. // the value change to "true".
  218. lacks_gettid = true;
  219. }
  220. #endif // OS_LINUX || OS_FREEBSD
  221. // If gettid() could not be used, we use one of the following.
  222. #if defined OS_LINUX
  223. return getpid(); // Linux: getpid returns thread ID when gettid is absent
  224. #elif defined OS_WINDOWS || defined OS_CYGWIN
  225. return GetCurrentThreadId();
  226. #else
  227. // If none of the techniques above worked, we use pthread_self().
  228. return (pid_t)(uintptr_t)pthread_self();
  229. #endif
  230. }
  231. const char* const_basename(const char* filepath) {
  232. const char* base = strrchr(filepath, '/');
  233. #ifdef OS_WINDOWS // Look for either path separator in Windows
  234. if (!base)
  235. base = strrchr(filepath, '\\');
  236. #endif
  237. return base ? (base+1) : filepath;
  238. }
  239. static string g_my_user_name;
  240. const string& MyUserName() {
  241. return g_my_user_name;
  242. }
  243. static void MyUserNameInitializer() {
  244. // TODO(hamaji): Probably this is not portable.
  245. #if defined(OS_WINDOWS)
  246. const char* user = getenv("USERNAME");
  247. #else
  248. const char* user = getenv("USER");
  249. #endif
  250. if (user != NULL) {
  251. g_my_user_name = user;
  252. } else {
  253. g_my_user_name = "invalid-user";
  254. }
  255. }
  256. REGISTER_MODULE_INITIALIZER(utilities, MyUserNameInitializer());
  257. #ifdef HAVE_STACKTRACE
  258. void DumpStackTraceToString(string* stacktrace) {
  259. DumpStackTrace(1, DebugWriteToString, stacktrace);
  260. }
  261. #endif
  262. // We use an atomic operation to prevent problems with calling CrashReason
  263. // from inside the Mutex implementation (potentially through RAW_CHECK).
  264. static const CrashReason* g_reason = 0;
  265. void SetCrashReason(const CrashReason* r) {
  266. sync_val_compare_and_swap(&g_reason,
  267. reinterpret_cast<const CrashReason*>(0),
  268. r);
  269. }
  270. void InitGoogleLoggingUtilities(const char* argv0) {
  271. CHECK(!IsGoogleLoggingInitialized())
  272. << "You called InitGoogleLogging() twice!";
  273. const char* slash = strrchr(argv0, '/');
  274. #ifdef OS_WINDOWS
  275. if (!slash) slash = strrchr(argv0, '\\');
  276. #endif
  277. g_program_invocation_short_name = slash ? slash + 1 : argv0;
  278. g_main_thread_id = pthread_self();
  279. #ifdef HAVE_STACKTRACE
  280. InstallFailureFunction(&DumpStackTraceAndExit);
  281. #endif
  282. }
  283. void ShutdownGoogleLoggingUtilities() {
  284. CHECK(IsGoogleLoggingInitialized())
  285. << "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
  286. #ifdef HAVE_SYSLOG_H
  287. closelog();
  288. #endif
  289. }
  290. } // namespace glog_internal_namespace_
  291. _END_GOOGLE_NAMESPACE_
  292. // Make an implementation of stacktrace compiled.
  293. #ifdef STACKTRACE_H
  294. # include STACKTRACE_H
  295. #endif