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()
24 _START_GOOGLE_NAMESPACE_
26 // Data for RawLog__ below. We simply pick up the latest
27 // time data created by a normal log message to avoid calling
28 // localtime_r which can allocate memory.
29 static struct ::tm last_tm_time_for_raw_log;
31 void RawLog__SetLastTime(const struct ::tm& t) {
32 memcpy(&last_tm_time_for_raw_log, &t, sizeof(last_tm_time_for_raw_log));
35 // CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
36 // that invoke malloc() and getenv() that might acquire some locks.
37 // If this becomes a problem we should reimplement a subset of vsnprintf
38 // that does not need locks and malloc.
40 // Helper for RawLog__ below.
41 // *DoRawLog writes to *buf of *size and move them past the written portion.
42 // It returns true iff there was no overflow or error.
43 static bool DoRawLog(char** buf, int* size, const char* format, ...) {
46 int n = vsnprintf(*buf, *size, format, ap);
48 if (n < 0 || n > *size) return false;
54 // Helper for RawLog__ below.
55 inline static bool VADoRawLog(char** buf, int* size,
56 const char* format, va_list ap) {
57 int n = vsnprintf(*buf, *size, format, ap);
58 if (n < 0 || n > *size) return false;
64 void RawLog__(LogSeverity severity, const char* file, int line,
65 const char* format, ...) {
66 if (!(FLAGS_logtostderr || severity >= FLAGS_stderrthreshold ||
67 FLAGS_alsologtostderr || !IsGoogleLoggingInitialized())) {
68 return; // this stderr log message is suppressed
70 // can't call localtime_r here: it can allocate
71 struct ::tm& t = last_tm_time_for_raw_log;
72 char buffer[3000]; // 3000 bytes should be enough for everyone... :-)
74 int size = sizeof(buffer);
75 if (is_default_thread()) {
76 DoRawLog(&buf, &size, "%c%02d%02d %02d%02d%02d %s:%d] RAW: ",
77 LogSeverityNames[severity][0],
78 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
79 const_basename(const_cast<char *>(file)), line);
81 DoRawLog(&buf, &size, "%c%02d%02d %02d%02d%02d %08x %s:%d] RAW: ",
82 LogSeverityNames[severity][0],
83 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec,
85 const_basename(const_cast<char *>(file)), line);
89 bool no_chop = VADoRawLog(&buf, &size, format, ap);
92 DoRawLog(&buf, &size, "\n");
94 DoRawLog(&buf, &size, "RAW_LOG ERROR: The Message was too long!\n");
96 // We make a raw syscall to write directly to the stderr file descriptor,
97 // avoiding FILE buffering (to avoid invoking malloc()), and bypassing
98 // libc (to side-step any libc interception).
99 // We write just once to avoid races with other invocations of RawLog__.
100 #if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
101 syscall(SYS_write, STDERR_FILENO, buffer, strlen(buffer));
103 write(STDERR_FILENO, buffer, strlen(buffer));
105 if (severity == FATAL) LogMessage::Fail();
108 _END_GOOGLE_NAMESPACE_