OR-Tools  8.1
logging_utilities.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <signal.h>
17 #include <stdio.h>
18 #if !defined(_MSC_VER)
19 #include <pwd.h>
20 #include <syslog.h>
21 #include <unistd.h> // For geteuid.
22 #endif
23 
24 #if defined(_MSC_VER) // windows compatibility layer.
25 #ifndef WIN32_LEAN_AND_MEAN
26 #define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
27 #endif
28 
29 #include <direct.h> /* for _getcwd() */
30 #include <io.h> /* because we so often use open/close/etc */
31 #include <process.h> /* for _getpid() */
32 #include <stdarg.h> /* template_dictionary.cc uses va_copy */
33 #include <string.h> /* for _strnicmp(), strerror_s() */
34 #include <time.h> /* for localtime_s() */
35 #include <windows.h>
36 #include <winsock.h> /* for gethostname */
37 /* Note: the C++ #includes are all together at the bottom. This file is
38  * used by both C and C++ code, so we put all the C++ together.
39  */
40 
41 /* 4244: otherwise we get problems when subtracting two size_t's to an int
42  * 4251: it's complaining about a private struct I've chosen not to dllexport
43  * 4355: we use this in a constructor, but we do it safely
44  * 4715: for some reason VC++ stopped realizing you can't return after abort()
45  * 4800: we know we're casting ints/char*'s to bools, and we're ok with that
46  * 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror()
47  * 4312: Converting uint32_t to a pointer when testing %p
48  * 4267: also subtracting two size_t to int
49  * 4722: Destructor never returns due to abort()
50  */
51 #pragma warning(disable : 4244 4251 4355 4715 4800 4996 4267 4312 4722)
52 
53 /* file I/O */
54 #define PATH_MAX 1024
55 #define access _access
56 #define getcwd _getcwd
57 #define open _open
58 #define read _read
59 #define write _write
60 #define lseek _lseek
61 #define close _close
62 #define popen _popen
63 #define pclose _pclose
64 #define R_OK 04 /* read-only (for access()) */
65 #define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR)
66 
67 #define O_WRONLY _O_WRONLY
68 #define O_CREAT _O_CREAT
69 #define O_EXCL _O_EXCL
70 
71 #ifndef __MINGW32__
72 enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
73 #endif
74 #define S_IRUSR S_IREAD
75 #define S_IWUSR S_IWRITE
76 
77 /* Not quite as lightweight as a hard-link, but more than good enough for us. */
78 #define link(oldpath, newpath) CopyFileA(oldpath, newpath, false)
79 
80 #define strcasecmp _stricmp
81 #define strncasecmp _strnicmp
82 
83 /* In windows-land, hash<> is called hash_compare<> (from xhash.h) */
84 /* VC11 provides std::hash */
85 #if defined(_MSC_VER) && (_MSC_VER < 1700)
86 #define hash hash_compare
87 #endif
88 
89 /* We can't just use _vsnprintf and _snprintf as drop-in-replacements,
90  * because they don't always NUL-terminate. :-( We also can't use the
91  * name vsnprintf, since windows defines that (but not snprintf (!)).
92  */
93 
94 // These call the windows _vsnprintf, but always NUL-terminate.
95 int safe_vsnprintf(char* str, size_t size, const char* format, va_list ap) {
96  if (size == 0) // not even room for a \0?
97  return -1; // not what C99 says to do, but what windows does
98  str[size - 1] = '\0';
99  return _vsnprintf(str, size - 1, format, ap);
100 }
101 
102 #define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
103 #ifndef va_copy
104 #define va_copy(dst, src) (dst) = (src)
105 #endif
106 
107 /* Windows doesn't support specifying the number of buckets as a
108  * hash_map constructor arg, so we leave this blank.
109  */
110 #define CTEMPLATE_SMALL_HASHTABLE
111 #define DEFAULT_TEMPLATE_ROOTDIR ".."
112 
113 // ----------------------------------- SYSTEM/PROCESS
114 typedef int pid_t;
115 #define getpid _getpid
116 
117 // ----------------------------------- THREADS
118 typedef DWORD pthread_t;
119 #define pthread_self GetCurrentThreadId
120 
121 inline struct tm* localtime_r(const time_t* timep, struct tm* result) {
122  localtime_s(result, timep);
123  return result;
124 }
125 
126 inline char* strerror_r(int errnum, char* buf, size_t buflen) {
127  strerror_s(buf, buflen, errnum);
128  return buf;
129 }
130 
131 #endif // _MSC_VER
132 
133 namespace google {
134 
135 static const char* g_program_invocation_short_name = NULL;
136 static pthread_t g_main_thread_id;
137 
138 } // namespace google
139 
140 // The following APIs are all internal.
141 #include "absl/debugging/failure_signal_handler.h"
142 #include "absl/debugging/stacktrace.h"
143 #include "absl/debugging/symbolize.h"
144 #include "absl/time/time.h"
146 
147 ABSL_FLAG(bool, symbolize_stacktrace, true,
148  "Symbolize the stack trace in the tombstone");
149 
150 namespace google {
151 
152 typedef void DebugWriter(const char*, void*);
153 
154 // The %p field width for printf() functions is two characters per byte.
155 // For some environments, add two extra bytes for the leading "0x".
156 static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
157 
158 static void DebugWriteToStderr(const char* data, void*) {
159  // This one is signal-safe.
160  if (write(STDERR_FILENO, data, strlen(data)) < 0) {
161  // Ignore errors.
162  }
163 }
164 
165 static void DebugWriteToString(const char* data, void* arg) {
166  reinterpret_cast<std::string*>(arg)->append(data);
167 }
168 
169 // Print a program counter and its symbol name.
170 static void DumpPCAndSymbol(DebugWriter* writerfn, void* arg, void* pc,
171  const char* const prefix) {
172  char tmp[1024];
173  const char* symbol = "(unknown)";
174  // Symbolizes the previous address of pc because pc may be in the
175  // next function. The overrun happens when the function ends with
176  // a call to a function annotated noreturn (e.g. CHECK).
177  if (absl::Symbolize(reinterpret_cast<char*>(pc) - 1, tmp, sizeof(tmp))) {
178  symbol = tmp;
179  }
180  char buf[1024];
181  snprintf(buf, sizeof(buf), "%s@ %*p %s\n", prefix, kPrintfPointerFieldWidth,
182  pc, symbol);
183  writerfn(buf, arg);
184 }
185 
186 static void DumpPC(DebugWriter* writerfn, void* arg, void* pc,
187  const char* const prefix) {
188  char buf[100];
189  snprintf(buf, sizeof(buf), "%s@ %*p\n", prefix, kPrintfPointerFieldWidth, pc);
190  writerfn(buf, arg);
191 }
192 
193 // Dump current stack trace as directed by writerfn
194 static void DumpStackTrace(int skip_count, DebugWriter* writerfn, void* arg) {
195  // Print stack trace
196  void* stack[32];
197  int depth = absl::GetStackTrace(stack, ABSL_ARRAYSIZE(stack), skip_count + 1);
198  for (int i = 0; i < depth; i++) {
199  if (absl::GetFlag(FLAGS_symbolize_stacktrace)) {
200  DumpPCAndSymbol(writerfn, arg, stack[i], " ");
201  } else {
202  DumpPC(writerfn, arg, stack[i], " ");
203  }
204  }
205 }
206 
207 static void DumpStackTraceAndExit() {
209  abort();
210 }
211 
212 namespace logging_internal {
213 
215  if (g_program_invocation_short_name != NULL) {
217  } else {
218  // TODO(user): Use /proc/self/cmdline and so?
219  return "UNKNOWN";
220  }
221 }
222 
224  return g_program_invocation_short_name != NULL;
225 }
226 
227 unsigned int GetTID() {
228  return static_cast<unsigned int>(absl::base_internal::GetTID());
229 }
230 
231 int64 CycleClock_Now() { return absl::ToUnixMicros(absl::Now()); }
232 
233 int64 UsecToCycles(int64 usec) { return usec; }
234 
235 static int32 g_main_thread_pid = getpid();
237 
238 const char* const_basename(const char* filepath) {
239  const char* base = strrchr(filepath, '/');
240 #ifdef _MSC_VER // Look for either path separator in Windows
241  if (!base) base = strrchr(filepath, '\\');
242 #endif
243  return base ? (base + 1) : filepath;
244 }
245 
246 static std::string g_my_user_name; // NOLINT
247 const std::string& MyUserName() { return g_my_user_name; }
248 static void MyUserNameInitializer() {
249 #if defined(_MSC_VER)
250  const char* user = getenv("USERNAME");
251 #else
252  const char* user = getenv("USER");
253 #endif
254  if (user != NULL) {
255  g_my_user_name = user;
256  } else {
257 #if !defined(_MSC_VER) // Not windows.
258  struct passwd pwd;
259  struct passwd* result = NULL;
260  char buffer[1024] = {'\0'};
261  uid_t uid = geteuid();
262  int pwuid_res = getpwuid_r(uid, &pwd, buffer, sizeof(buffer), &result);
263  if (pwuid_res == 0) {
264  g_my_user_name = pwd.pw_name;
265  } else {
266  snprintf(buffer, sizeof(buffer), "uid%d", uid);
267  g_my_user_name = buffer;
268  }
269 #endif // _defined(_MSC_VER)
270  if (g_my_user_name.empty()) {
271  g_my_user_name = "invalid-user";
272  }
273  }
274 }
275 
277  public:
278  typedef void (*void_function)(void);
279  GoogleInitializer(const char*, void_function f) { f(); }
280 };
281 
282 #define REGISTER_MODULE_INITIALIZER(name, body) \
283  namespace { \
284  static void google_init_module_##name() { body; } \
285  GoogleInitializer google_initializer_module_##name( \
286  #name, google_init_module_##name); \
287  }
288 
290 
291 void DumpStackTraceToString(std::string* stacktrace) {
292  DumpStackTrace(1, DebugWriteToString, stacktrace);
293 }
294 
295 // We use an atomic operation to prevent problems with calling CrashReason
296 // from inside the Mutex implementation (potentially through RAW_CHECK).
297 static const CrashReason* g_reason = 0;
298 
299 void SetCrashReason(const CrashReason* r) {
300  sync_val_compare_and_swap(&g_reason, reinterpret_cast<const CrashReason*>(0),
301  r);
302 }
303 
304 void InitGoogleLoggingUtilities(const char* argv0) {
306  << "You called InitGoogleLogging() twice!";
307  const char* slash = strrchr(argv0, '/');
308 #ifdef _MSC_VER
309  if (!slash) slash = strrchr(argv0, '\\');
310 #endif
311  g_program_invocation_short_name = slash ? slash + 1 : argv0;
312  g_main_thread_id = pthread_self();
313 
315 }
316 
319  << "You called ShutdownGoogleLogging() without calling "
320  "InitGoogleLogging() first!";
322 #if !defined(_MSC_VER)
323  closelog();
324 #endif // !defined(_MSC_VER)
325 }
326 
327 } // namespace logging_internal
328 
329 } // namespace google
google::logging_internal::GoogleInitializer::void_function
void(* void_function)(void)
Definition: logging_utilities.cc:278
google::logging_internal::g_reason
static const CrashReason * g_reason
Definition: logging_utilities.cc:297
google::DebugWriter
void DebugWriter(const char *, void *)
Definition: logging_utilities.cc:152
google::logging_internal::IsGoogleLoggingInitialized
bool IsGoogleLoggingInitialized()
Definition: logging_utilities.cc:223
google::DumpStackTraceAndExit
static void DumpStackTraceAndExit()
Definition: logging_utilities.cc:207
google::logging_internal::ProgramInvocationShortName
const char * ProgramInvocationShortName()
Definition: logging_utilities.cc:214
ABSL_FLAG
ABSL_FLAG(bool, symbolize_stacktrace, true, "Symbolize the stack trace in the tombstone")
logging_utilities.h
google::logging_internal::sync_val_compare_and_swap
T sync_val_compare_and_swap(T *ptr, T oldval, T newval)
Definition: logging_utilities.h:50
int64
int64_t int64
Definition: integral_types.h:34
google::g_program_invocation_short_name
static const char * g_program_invocation_short_name
Definition: logging_utilities.cc:135
google::logging_internal::GoogleInitializer
Definition: logging_utilities.cc:276
int32
int int32
Definition: integral_types.h:33
google::DebugWriteToStderr
static void DebugWriteToStderr(const char *data, void *)
Definition: logging_utilities.cc:158
google::logging_internal::GetMainThreadPid
int32 GetMainThreadPid()
Definition: logging_utilities.cc:236
google::logging_internal::MyUserName
const std::string & MyUserName()
Definition: logging_utilities.cc:247
google::logging_internal::GetTID
unsigned int GetTID()
Definition: logging_utilities.cc:227
google::logging_internal::MyUserNameInitializer
static void MyUserNameInitializer()
Definition: logging_utilities.cc:248
google::DumpPC
static void DumpPC(DebugWriter *writerfn, void *arg, void *pc, const char *const prefix)
Definition: logging_utilities.cc:186
google::logging_internal::SetCrashReason
void SetCrashReason(const CrashReason *r)
Definition: logging_utilities.cc:299
google::DebugWriteToString
static void DebugWriteToString(const char *data, void *arg)
Definition: logging_utilities.cc:165
google::logging_internal::CycleClock_Now
int64 CycleClock_Now()
Definition: logging_utilities.cc:231
google::logging_internal::g_my_user_name
static std::string g_my_user_name
Definition: logging_utilities.cc:246
google::logging_internal::REGISTER_MODULE_INITIALIZER
REGISTER_MODULE_INITIALIZER(logging_utilities, MyUserNameInitializer())
google::DumpStackTrace
static void DumpStackTrace(int skip_count, DebugWriter *writerfn, void *arg)
Definition: logging_utilities.cc:194
google::logging_internal::DumpStackTraceToString
void DumpStackTraceToString(std::string *stacktrace)
Definition: logging_utilities.cc:291
google::g_main_thread_id
static pthread_t g_main_thread_id
Definition: logging_utilities.cc:136
google::logging_internal::GoogleInitializer::GoogleInitializer
GoogleInitializer(const char *, void_function f)
Definition: logging_utilities.cc:279
google::InstallFailureFunction
void InstallFailureFunction(void(*fail_func)())
Definition: base/logging.cc:1388
io.h
google::logging_internal::ShutdownGoogleLoggingUtilities
void ShutdownGoogleLoggingUtilities()
Definition: logging_utilities.cc:317
google::logging_internal::g_main_thread_pid
static int32 g_main_thread_pid
Definition: logging_utilities.cc:235
google::logging_internal::const_basename
const char * const_basename(const char *filepath)
Definition: logging_utilities.cc:238
google::DumpPCAndSymbol
static void DumpPCAndSymbol(DebugWriter *writerfn, void *arg, void *pc, const char *const prefix)
Definition: logging_utilities.cc:170
google::kPrintfPointerFieldWidth
static const int kPrintfPointerFieldWidth
Definition: logging_utilities.cc:156
google::logging_internal::UsecToCycles
int64 UsecToCycles(int64 usec)
Definition: logging_utilities.cc:233
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
commandlineflags.h
google
Definition: log_severity.h:24
google::logging_internal::InitGoogleLoggingUtilities
void InitGoogleLoggingUtilities(const char *argv0)
Definition: logging_utilities.cc:304
google::logging_internal::CrashReason
Definition: logging_utilities.h:64