raw_logging.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #include <stddef.h>
18 #include <cstdarg>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 
23 #include "absl/base/attributes.h"
24 #include "absl/base/config.h"
26 #include "absl/base/log_severity.h"
27 
28 // We know how to perform low-level writes to stderr in POSIX and Windows. For
29 // these platforms, we define the token ABSL_LOW_LEVEL_WRITE_SUPPORTED.
30 // Much of raw_logging.cc becomes a no-op when we can't output messages,
31 // although a FATAL ABSL_RAW_LOG message will still abort the process.
32 
33 // ABSL_HAVE_POSIX_WRITE is defined when the platform provides posix write()
34 // (as from unistd.h)
35 //
36 // This preprocessor token is also defined in raw_io.cc. If you need to copy
37 // this, consider moving both to config.h instead.
38 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
39  defined(__Fuchsia__) || defined(__native_client__) || \
40  defined(__EMSCRIPTEN__)
41 #include <unistd.h>
42 
43 
44 #define ABSL_HAVE_POSIX_WRITE 1
45 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
46 #else
47 #undef ABSL_HAVE_POSIX_WRITE
48 #endif
49 
50 // ABSL_HAVE_SYSCALL_WRITE is defined when the platform provides the syscall
51 // syscall(SYS_write, /*int*/ fd, /*char* */ buf, /*size_t*/ len);
52 // for low level operations that want to avoid libc.
53 #if (defined(__linux__) || defined(__FreeBSD__)) && !defined(__ANDROID__)
54 #include <sys/syscall.h>
55 #define ABSL_HAVE_SYSCALL_WRITE 1
56 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
57 #else
58 #undef ABSL_HAVE_SYSCALL_WRITE
59 #endif
60 
61 #ifdef _WIN32
62 #include <io.h>
63 
64 #define ABSL_HAVE_RAW_IO 1
65 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
66 #else
67 #undef ABSL_HAVE_RAW_IO
68 #endif
69 
70 // TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
71 // Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
72 // whitelisted set of platforms for which we expect not to be able to raw log.
73 
78 
79 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
80 static const char kTruncated[] = " ... (message truncated)\n";
81 
82 // sprintf the format to the buffer, adjusting *buf and *size to reflect the
83 // consumed bytes, and return whether the message fit without truncation. If
84 // truncation occurred, if possible leave room in the buffer for the message
85 // kTruncated[].
86 inline static bool VADoRawLog(char** buf, int* size, const char* format,
87  va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
88 inline static bool VADoRawLog(char** buf, int* size,
89  const char* format, va_list ap) {
90  int n = vsnprintf(*buf, *size, format, ap);
91  bool result = true;
92  if (n < 0 || n > *size) {
93  result = false;
94  if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
95  n = *size - sizeof(kTruncated); // room for truncation message
96  } else {
97  n = 0; // no room for truncation message
98  }
99  }
100  *size -= n;
101  *buf += n;
102  return result;
103 }
104 #endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED
105 
106 static constexpr int kLogBufSize = 3000;
107 
108 namespace {
109 
110 // CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
111 // that invoke malloc() and getenv() that might acquire some locks.
112 
113 // Helper for RawLog below.
114 // *DoRawLog writes to *buf of *size and move them past the written portion.
115 // It returns true iff there was no overflow or error.
116 bool DoRawLog(char** buf, int* size, const char* format, ...)
117  ABSL_PRINTF_ATTRIBUTE(3, 4);
118 bool DoRawLog(char** buf, int* size, const char* format, ...) {
119  va_list ap;
120  va_start(ap, format);
121  int n = vsnprintf(*buf, *size, format, ap);
122  va_end(ap);
123  if (n < 0 || n > *size) return false;
124  *size -= n;
125  *buf += n;
126  return true;
127 }
128 
129 void RawLogVA(absl::LogSeverity severity, const char* file, int line,
130  const char* format, va_list ap) ABSL_PRINTF_ATTRIBUTE(4, 0);
131 void RawLogVA(absl::LogSeverity severity, const char* file, int line,
132  const char* format, va_list ap) {
133  char buffer[kLogBufSize];
134  char* buf = buffer;
135  int size = sizeof(buffer);
136 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
137  bool enabled = true;
138 #else
139  bool enabled = false;
140 #endif
141 
142 #ifdef ABSL_MIN_LOG_LEVEL
143  if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
144  severity < absl::LogSeverity::kFatal) {
145  enabled = false;
146  }
147 #endif
148 
149  auto log_prefix_hook_ptr = log_prefix_hook.Load();
150  if (log_prefix_hook_ptr) {
151  enabled = log_prefix_hook_ptr(severity, file, line, &buf, &size);
152  } else {
153  if (enabled) {
154  DoRawLog(&buf, &size, "[%s : %d] RAW: ", file, line);
155  }
156  }
157  const char* const prefix_end = buf;
158 
159 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
160  if (enabled) {
161  bool no_chop = VADoRawLog(&buf, &size, format, ap);
162  if (no_chop) {
163  DoRawLog(&buf, &size, "\n");
164  } else {
165  DoRawLog(&buf, &size, "%s", kTruncated);
166  }
167  absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
168  }
169 #else
170  static_cast<void>(format);
171  static_cast<void>(ap);
172 #endif
173 
174  // Abort the process after logging a FATAL message, even if the output itself
175  // was suppressed.
176  if (severity == absl::LogSeverity::kFatal) {
177  abort_hook(file, line, buffer, prefix_end, buffer + kLogBufSize);
178  abort();
179  }
180 }
181 
182 } // namespace
183 
184 namespace absl {
185 namespace raw_logging_internal {
186 void SafeWriteToStderr(const char *s, size_t len) {
187 #if defined(ABSL_HAVE_SYSCALL_WRITE)
188  syscall(SYS_write, STDERR_FILENO, s, len);
189 #elif defined(ABSL_HAVE_POSIX_WRITE)
190  write(STDERR_FILENO, s, len);
191 #elif defined(ABSL_HAVE_RAW_IO)
192  _write(/* stderr */ 2, s, len);
193 #else
194  // stderr logging unsupported on this platform
195  (void) s;
196  (void) len;
197 #endif
198 }
199 
200 void RawLog(absl::LogSeverity severity, const char* file, int line,
201  const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
202 void RawLog(absl::LogSeverity severity, const char* file, int line,
203  const char* format, ...) {
204  va_list ap;
205  va_start(ap, format);
206  RawLogVA(severity, file, line, format, ap);
207  va_end(ap);
208 }
209 
210 // Non-formatting version of RawLog().
211 //
212 // TODO(gfalcon): When string_view no longer depends on base, change this
213 // interface to take its message as a string_view instead.
214 static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
215  int line, const std::string& message) {
216  RawLog(severity, file, line, "%s", message.c_str());
217 }
218 
220 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
221  return true;
222 #else // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
223  return false;
224 #endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
225 }
226 
229 
231  internal_log_function.Store(func);
232 }
233 
234 } // namespace raw_logging_internal
235 } // namespace absl
void SafeWriteToStderr(const char *s, size_t len)
Definition: raw_logging.cc:186
#define ABSL_CONST_INIT
Definition: attributes.h:605
LogSeverity
Definition: log_severity.h:28
void RegisterInternalLogFunction(InternalLogFunction func)
Definition: raw_logging.cc:230
static ABSL_CONST_INIT absl::base_internal::AtomicHook< absl::raw_logging_internal::LogPrefixHook > log_prefix_hook
Definition: raw_logging.cc:75
char buf[N]
Definition: algorithm.h:29
bool(*)(absl::LogSeverity severity, const char *file, int line, char **buffer, int *buf_size) LogPrefixHook
Definition: raw_logging.h:152
base_internal::AtomicHook< InternalLogFunction > internal_log_function
static ABSL_CONST_INIT absl::base_internal::AtomicHook< absl::raw_logging_internal::AbortHook > abort_hook
Definition: raw_logging.cc:77
std::string format(const std::string &, const time_point< seconds > &, const femtoseconds &, const time_zone &)
uintptr_t size
static void DefaultInternalLog(absl::LogSeverity severity, const char *file, int line, const std::string &message)
Definition: raw_logging.cc:214
void RawLog(absl::LogSeverity severity, const char *file, int line, const char *format,...) ABSL_PRINTF_ATTRIBUTE(4
Definition: raw_logging.cc:202
void(*)(absl::LogSeverity severity, const char *file, int line, const std::string &message) InternalLogFunction
Definition: raw_logging.h:172
static constexpr int kLogBufSize
Definition: raw_logging.cc:106
#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition: attributes.h:116
void(*)(const char *file, int line, const char *buf_start, const char *prefix_end, const char *buf_end) AbortHook
Definition: raw_logging.h:164


abseil_cpp
Author(s):
autogenerated on Tue Jun 18 2019 19:44:37