Initial windows support. Now we don't have the stacktrace and several unittests.
[platform/upstream/glog.git] / src / raw_logging.cc
1 // Copyright 2006 Google Inc. All Rights Reserved.
2 // Author: Maxim Lifantsev
3 //
4 // logging_unittest.cc covers the functionality herein
5
6 #include "utilities.h"
7
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <time.h>
11 #include "config.h"
12 #include "glog/logging.h"          // To pick up flag settings etc.
13 #include "glog/raw_logging.h"
14
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()
19 #endif
20 #ifdef HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23
24 _START_GOOGLE_NAMESPACE_
25
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;
30
31 void RawLog__SetLastTime(const struct ::tm& t) {
32   memcpy(&last_tm_time_for_raw_log, &t, sizeof(last_tm_time_for_raw_log));
33 }
34
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.
39
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, ...) {
44   va_list ap;
45   va_start(ap, format);
46   int n = vsnprintf(*buf, *size, format, ap);
47   va_end(ap);
48   if (n < 0 || n > *size) return false;
49   *size -= n;
50   *buf += n;
51   return true;
52 }
53
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;
59   *size -= n;
60   *buf += n;
61   return true;
62 }
63
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
69   }
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... :-)
73   char* buf = buffer;
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);
80   } else {
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,
84              int(pthread_self()),
85              const_basename(const_cast<char *>(file)), line);
86   }
87   va_list ap;
88   va_start(ap, format);
89   bool no_chop = VADoRawLog(&buf, &size, format, ap);
90   va_end(ap);
91   if (no_chop) {
92     DoRawLog(&buf, &size, "\n");
93   } else {
94     DoRawLog(&buf, &size, "RAW_LOG ERROR: The Message was too long!\n");
95   }
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));
102 #else
103   write(STDERR_FILENO, buffer, strlen(buffer));
104 #endif
105   if (severity == FATAL)  LogMessage::Fail();
106 }
107
108 _END_GOOGLE_NAMESPACE_