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