1 // Copyright 2006 Google Inc. All Rights Reserved.
2 // Author: Maxim Lifantsev
4 // logging_unittest.cc covers the functionality herein
12 #include "glog/logging.h" // To pick up flag settings etc.
13 #include "glog/raw_logging.h"
15 #if defined(HAVE_SYSCALL_H)
16 #include <syscall.h> // for syscall()
17 #elif defined(HAVE_SYS_SYSCALL_H)
18 #include <sys/syscall.h> // for syscall()
22 #if defined(OS_MACOSX)
23 #ifndef __DARWIN_UNIX03
24 #define __DARWIN_UNIX03 // tells libgen.h to define basename()
28 #include <libgen.h> // basename()
30 _START_GOOGLE_NAMESPACE_
32 // Data for RawLog__ below. We simply pick up the latest
33 // time data created by a normal log message to avoid calling
34 // localtime_r which can allocate memory.
35 static struct ::tm last_tm_time_for_raw_log;
37 void RawLog__SetLastTime(const struct ::tm& t) {
38 memcpy(&last_tm_time_for_raw_log, &t, sizeof(last_tm_time_for_raw_log));
41 // CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
42 // that invoke malloc() and getenv() that might acquire some locks.
43 // If this becomes a problem we should reimplement a subset of vsnprintf
44 // that does not need locks and malloc.
46 // Helper for RawLog__ below.
47 // *DoRawLog writes to *buf of *size and move them past the written portion.
48 // It returns true iff there was no overflow or error.
49 static bool DoRawLog(char** buf, int* size, const char* format, ...) {
52 int n = vsnprintf(*buf, *size, format, ap);
54 if (n < 0 || n > *size) return false;
60 // Helper for RawLog__ below.
61 inline static bool VADoRawLog(char** buf, int* size,
62 const char* format, va_list ap) {
63 int n = vsnprintf(*buf, *size, format, ap);
64 if (n < 0 || n > *size) return false;
70 void RawLog__(LogSeverity severity, const char* file, int line,
71 const char* format, ...) {
72 if (!(FLAGS_logtostderr || severity >= FLAGS_stderrthreshold ||
73 FLAGS_alsologtostderr || !IsGoogleLoggingInitialized())) {
74 return; // this stderr log message is suppressed
76 // can't call localtime_r here: it can allocate
77 struct ::tm& t = last_tm_time_for_raw_log;
78 char buffer[3000]; // 3000 bytes should be enough for everyone... :-)
80 int size = sizeof(buffer);
81 if (is_default_thread()) {
82 DoRawLog(&buf, &size, "%c%02d%02d %02d%02d%02d %s:%d] RAW: ",
83 LogSeverityNames[severity][0],
84 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
85 basename(const_cast<char *>(file)), line);
87 DoRawLog(&buf, &size, "%c%02d%02d %02d%02d%02d %08x %s:%d] RAW: ",
88 LogSeverityNames[severity][0],
89 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
91 basename(const_cast<char *>(file)), line);
95 bool no_chop = VADoRawLog(&buf, &size, format, ap);
98 DoRawLog(&buf, &size, "\n");
100 DoRawLog(&buf, &size, "RAW_LOG ERROR: The Message was too long!\n");
102 // We make a raw syscall to write directly to the stderr file descriptor,
103 // avoiding FILE buffering (to avoid invoking malloc()), and bypassing
104 // libc (to side-step any libc interception).
105 // We write just once to avoid races with other invocations of RawLog__.
106 #if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
107 syscall(SYS_write, STDERR_FILENO, buffer, strlen(buffer));
109 write(STDERR_FILENO, buffer, strlen(buffer));
111 if (severity == FATAL) LogMessage::Fail();
114 _END_GOOGLE_NAMESPACE_