• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "absl/log/internal/log_message.h"
17 
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #ifndef _WIN32
24 #include <unistd.h>
25 #endif
26 
27 #include <algorithm>
28 #include <array>
29 #include <atomic>
30 #include <memory>
31 #include <ostream>
32 #include <string>
33 #include <tuple>
34 
35 #include "absl/base/attributes.h"
36 #include "absl/base/config.h"
37 #include "absl/base/internal/raw_logging.h"
38 #include "absl/base/internal/strerror.h"
39 #include "absl/base/internal/sysinfo.h"
40 #include "absl/base/log_severity.h"
41 #include "absl/container/inlined_vector.h"
42 #include "absl/debugging/internal/examine_stack.h"
43 #include "absl/log/globals.h"
44 #include "absl/log/internal/config.h"
45 #include "absl/log/internal/globals.h"
46 #include "absl/log/internal/log_format.h"
47 #include "absl/log/internal/log_sink_set.h"
48 #include "absl/log/log_entry.h"
49 #include "absl/log/log_sink.h"
50 #include "absl/log/log_sink_registry.h"
51 #include "absl/memory/memory.h"
52 #include "absl/strings/str_format.h"
53 #include "absl/strings/string_view.h"
54 #include "absl/time/clock.h"
55 #include "absl/time/time.h"
56 #include "absl/types/span.h"
57 
ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)58 extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
59     AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
60   // Default - Do nothing
61 }
62 
63 namespace absl {
64 ABSL_NAMESPACE_BEGIN
65 namespace log_internal {
66 
67 namespace {
68 // Copies into `dst` as many bytes of `src` as will fit, then truncates the
69 // copied bytes from the front of `dst` and returns the number of bytes written.
AppendTruncated(absl::string_view src,absl::Span<char> * dst)70 size_t AppendTruncated(absl::string_view src, absl::Span<char>* dst) {
71   if (src.size() > dst->size()) src = src.substr(0, dst->size());
72   memcpy(dst->data(), src.data(), src.size());
73   dst->remove_prefix(src.size());
74   return src.size();
75 }
76 
Basename(absl::string_view filepath)77 absl::string_view Basename(absl::string_view filepath) {
78 #ifdef _WIN32
79   size_t path = filepath.find_last_of("/\\");
80 #else
81   size_t path = filepath.find_last_of('/');
82 #endif
83   if (path != filepath.npos) filepath.remove_prefix(path + 1);
84   return filepath;
85 }
86 
WriteToString(const char * data,void * str)87 void WriteToString(const char* data, void* str) {
88   reinterpret_cast<std::string*>(str)->append(data);
89 }
WriteToStream(const char * data,void * os)90 void WriteToStream(const char* data, void* os) {
91   auto* cast_os = static_cast<std::ostream*>(os);
92   *cast_os << data;
93 }
94 }  // namespace
95 
96 // A write-only `std::streambuf` that writes into an `absl::Span<char>`.
97 //
98 // This class is responsible for writing a metadata prefix just before the first
99 // data are streamed in.  The metadata are subject to change (cf.
100 // `LogMessage::AtLocation`) until then, so we wait as long as possible.
101 //
102 // This class is also responsible for reserving space for a trailing newline
103 // so that one can be added later by `Finalize` no matter how many data are
104 // streamed in.
105 class LogEntryStreambuf final : public std::streambuf {
106  public:
LogEntryStreambuf(absl::Span<char> buf,const absl::LogEntry & entry)107   explicit LogEntryStreambuf(absl::Span<char> buf, const absl::LogEntry& entry)
108       : buf_(buf), entry_(entry), prefix_len_(0), finalized_(false) {
109     // To detect when data are first written, we leave the put area null,
110     // override `overflow`, and check ourselves in `xsputn`.
111   }
112 
113   LogEntryStreambuf(LogEntryStreambuf&&) = delete;
114   LogEntryStreambuf& operator=(LogEntryStreambuf&&) = delete;
115 
Finalize()116   absl::Span<const char> Finalize() {
117     assert(!finalized_);
118     // If no data were ever streamed in, this is where we must write the prefix.
119     if (pbase() == nullptr) Initialize();
120     // Here we reclaim the two bytes we reserved.
121     ptrdiff_t idx = pptr() - pbase();
122     setp(buf_.data(), buf_.data() + buf_.size());
123     pbump(static_cast<int>(idx));
124     sputc('\n');
125     sputc('\0');
126     finalized_ = true;
127     return absl::Span<const char>(pbase(),
128                                   static_cast<size_t>(pptr() - pbase()));
129   }
prefix_len() const130   size_t prefix_len() const { return prefix_len_; }
131 
132  protected:
xsputn(const char * s,std::streamsize n)133   std::streamsize xsputn(const char* s, std::streamsize n) override {
134     if (n < 0) return 0;
135     if (pbase() == nullptr) Initialize();
136     return static_cast<std::streamsize>(
137         Append(absl::string_view(s, static_cast<size_t>(n))));
138   }
139 
overflow(int ch=EOF)140   int overflow(int ch = EOF) override {
141     if (pbase() == nullptr) Initialize();
142     if (ch == EOF) return 0;
143     if (pptr() == epptr()) return EOF;
144     *pptr() = static_cast<char>(ch);
145     pbump(1);
146     return 1;
147   }
148 
149  private:
Initialize()150   void Initialize() {
151     // Here we reserve two bytes in our buffer to guarantee `Finalize` space to
152     // add a trailing "\n\0".
153     assert(buf_.size() >= 2);
154     setp(buf_.data(), buf_.data() + buf_.size() - 2);
155     if (entry_.prefix()) {
156       absl::Span<char> remaining = buf_;
157       prefix_len_ = log_internal::FormatLogPrefix(
158           entry_.log_severity(), entry_.timestamp(), entry_.tid(),
159           entry_.source_basename(), entry_.source_line(), remaining);
160       pbump(static_cast<int>(prefix_len_));
161     }
162   }
163 
Append(absl::string_view data)164   size_t Append(absl::string_view data) {
165     absl::Span<char> remaining(pptr(), static_cast<size_t>(epptr() - pptr()));
166     const size_t written = AppendTruncated(data, &remaining);
167     pbump(static_cast<int>(written));
168     return written;
169   }
170 
171   const absl::Span<char> buf_;
172   const absl::LogEntry& entry_;
173   size_t prefix_len_;
174   bool finalized_;
175 };
176 
177 struct LogMessage::LogMessageData final {
178   LogMessageData(const char* file, int line, absl::LogSeverity severity,
179                  absl::Time timestamp);
180   LogMessageData(const LogMessageData&) = delete;
181   LogMessageData& operator=(const LogMessageData&) = delete;
182 
183   // `LogEntry` sent to `LogSink`s; contains metadata.
184   absl::LogEntry entry;
185 
186   // true => this was first fatal msg
187   bool first_fatal;
188   // true => all failures should be quiet
189   bool fail_quietly;
190   // true => PLOG was requested
191   bool is_perror;
192 
193   // Extra `LogSink`s to log to, in addition to `global_sinks`.
194   absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
195   // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
196   // non-sink targets (e.g. stderr, log files).
197   bool extra_sinks_only;
198 
199   // A formatted string message is built in `string_buf`.
200   std::array<char, kLogMessageBufferSize> string_buf;
201 
202   // A `std::streambuf` that stores into `string_buf`.
203   LogEntryStreambuf streambuf_;
204 };
205 
LogMessageData(const char * file,int line,absl::LogSeverity severity,absl::Time timestamp)206 LogMessage::LogMessageData::LogMessageData(const char* file, int line,
207                                            absl::LogSeverity severity,
208                                            absl::Time timestamp)
209     : extra_sinks_only(false),
210       streambuf_(absl::MakeSpan(string_buf), entry) {
211   entry.full_filename_ = file;
212   entry.base_filename_ = Basename(file);
213   entry.line_ = line;
214   entry.prefix_ = absl::ShouldPrependLogPrefix();
215   entry.severity_ = absl::NormalizeLogSeverity(severity);
216   entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
217   entry.timestamp_ = timestamp;
218   entry.tid_ = absl::base_internal::GetCachedTID();
219 }
220 
LogMessage(const char * file,int line,absl::LogSeverity severity)221 LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
222     : data_(
223           absl::make_unique<LogMessageData>(file, line, severity, absl::Now()))
224       ,
225       stream_(&data_->streambuf_)
226 {
227   data_->first_fatal = false;
228   data_->is_perror = false;
229   data_->fail_quietly = false;
230 
231   // Legacy defaults for LOG's ostream:
232   stream_.setf(std::ios_base::showbase | std::ios_base::boolalpha);
233   // `fill('0')` is omitted here because its effects are very different without
234   // structured logging.  Resolution is tracked in b/111310488.
235 
236   // This logs a backtrace even if the location is subsequently changed using
237   // AtLocation.  This quirk, and the behavior when AtLocation is called twice,
238   // are fixable but probably not worth fixing.
239   LogBacktraceIfNeeded();
240 }
241 
~LogMessage()242 LogMessage::~LogMessage() {
243 #ifdef ABSL_MIN_LOG_LEVEL
244   if (data_->entry.log_severity() <
245           static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
246       data_->entry.log_severity() < absl::LogSeverity::kFatal) {
247     return;
248   }
249 #endif
250   Flush();
251 }
252 
AtLocation(absl::string_view file,int line)253 LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
254   data_->entry.full_filename_ = file;
255   data_->entry.base_filename_ = Basename(file);
256   data_->entry.line_ = line;
257   LogBacktraceIfNeeded();
258   return *this;
259 }
260 
NoPrefix()261 LogMessage& LogMessage::NoPrefix() {
262   data_->entry.prefix_ = false;
263   return *this;
264 }
265 
WithVerbosity(int verbose_level)266 LogMessage& LogMessage::WithVerbosity(int verbose_level) {
267   if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
268     data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
269   } else {
270     data_->entry.verbose_level_ = std::max(0, verbose_level);
271   }
272   return *this;
273 }
274 
WithTimestamp(absl::Time timestamp)275 LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
276   data_->entry.timestamp_ = timestamp;
277   return *this;
278 }
279 
WithThreadID(absl::LogEntry::tid_t tid)280 LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
281   data_->entry.tid_ = tid;
282   return *this;
283 }
284 
WithMetadataFrom(const absl::LogEntry & entry)285 LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
286   data_->entry.full_filename_ = entry.full_filename_;
287   data_->entry.base_filename_ = entry.base_filename_;
288   data_->entry.line_ = entry.line_;
289   data_->entry.prefix_ = entry.prefix_;
290   data_->entry.severity_ = entry.severity_;
291   data_->entry.verbose_level_ = entry.verbose_level_;
292   data_->entry.timestamp_ = entry.timestamp_;
293   data_->entry.tid_ = entry.tid_;
294   return *this;
295 }
296 
WithPerror()297 LogMessage& LogMessage::WithPerror() {
298   data_->is_perror = true;
299   return *this;
300 }
301 
ToSinkAlso(absl::LogSink * sink)302 LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
303   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
304   data_->extra_sinks.push_back(sink);
305   return *this;
306 }
307 
ToSinkOnly(absl::LogSink * sink)308 LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
309   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
310   data_->extra_sinks.clear();
311   data_->extra_sinks.push_back(sink);
312   data_->extra_sinks_only = true;
313   return *this;
314 }
315 
316 #ifdef __ELF__
317 extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
318 extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
319 #endif
320 
FailWithoutStackTrace()321 void LogMessage::FailWithoutStackTrace() {
322   // Now suppress repeated trace logging:
323   log_internal::SetSuppressSigabortTrace(true);
324 #if defined _DEBUG && defined COMPILER_MSVC
325   // When debugging on windows, avoid the obnoxious dialog.
326   __debugbreak();
327 #endif
328 
329 #ifdef __ELF__
330   // For b/8737634, flush coverage if we are in coverage mode.
331   if (&__gcov_dump != nullptr) {
332     __gcov_dump();
333   } else if (&__gcov_flush != nullptr) {
334     __gcov_flush();
335   }
336 #endif
337 
338   abort();
339 }
340 
FailQuietly()341 void LogMessage::FailQuietly() {
342   // _exit. Calling abort() would trigger all sorts of death signal handlers
343   // and a detailed stack trace. Calling exit() would trigger the onexit
344   // handlers, including the heap-leak checker, which is guaranteed to fail in
345   // this case: we probably just new'ed the std::string that we logged.
346   // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
347   // of the program quickly, and it doesn't make much sense for FailQuietly to
348   // offer different guarantees about exit behavior than Fail does. (And as a
349   // consequence for QCHECK and CHECK to offer different exit behaviors)
350   _exit(1);
351 }
352 
353 template LogMessage& LogMessage::operator<<(const char& v);
354 template LogMessage& LogMessage::operator<<(const signed char& v);
355 template LogMessage& LogMessage::operator<<(const unsigned char& v);
356 template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
357 template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
358 template LogMessage& LogMessage::operator<<(const int& v);
359 template LogMessage& LogMessage::operator<<(const unsigned int& v);
360 template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
361 template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
362 template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
363 template LogMessage& LogMessage::operator<<(
364     const unsigned long long& v);  // NOLINT
365 template LogMessage& LogMessage::operator<<(void* const& v);
366 template LogMessage& LogMessage::operator<<(const void* const& v);
367 template LogMessage& LogMessage::operator<<(const float& v);
368 template LogMessage& LogMessage::operator<<(const double& v);
369 template LogMessage& LogMessage::operator<<(const bool& v);
370 template LogMessage& LogMessage::operator<<(const std::string& v);
371 template LogMessage& LogMessage::operator<<(const absl::string_view& v);
372 
Flush()373 void LogMessage::Flush() {
374   if (data_->entry.log_severity() < absl::MinLogLevel())
375     return;
376 
377   if (data_->is_perror) {
378     InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
379                      << " [" << errno_saver_() << "]";
380   }
381 
382   // Have we already seen a fatal message?
383   ABSL_CONST_INIT static std::atomic_flag seen_fatal = ATOMIC_FLAG_INIT;
384   if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
385       absl::log_internal::ExitOnDFatal()) {
386     // Exactly one LOG(FATAL) message is responsible for aborting the process,
387     // even if multiple threads LOG(FATAL) concurrently.
388     data_->first_fatal = !seen_fatal.test_and_set(std::memory_order_relaxed);
389   }
390 
391   data_->entry.text_message_with_prefix_and_newline_and_nul_ =
392       data_->streambuf_.Finalize();
393   data_->entry.prefix_len_ = data_->streambuf_.prefix_len();
394   SendToLog();
395 }
396 
SetFailQuietly()397 void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
398 
IsFatal() const399 bool LogMessage::IsFatal() const {
400   return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
401          absl::log_internal::ExitOnDFatal();
402 }
403 
PrepareToDie()404 void LogMessage::PrepareToDie() {
405   // If we log a FATAL message, flush all the log destinations, then toss
406   // a signal for others to catch. We leave the logs in a state that
407   // someone else can use them (as long as they flush afterwards)
408   if (data_->first_fatal) {
409     // Notify observers about the upcoming fatal error.
410     ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
411   }
412 
413   if (!data_->fail_quietly) {
414     // Log the message first before we start collecting stack trace.
415     log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
416                              data_->extra_sinks_only);
417 
418     // `DumpStackTrace` generates an empty string under MSVC.
419     // Adding the constant prefix here simplifies testing.
420     data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
421     debugging_internal::DumpStackTrace(
422         0, log_internal::MaxFramesInLogStackTrace(),
423         log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
424         &data_->entry.stacktrace_);
425   }
426 }
427 
Die()428 void LogMessage::Die() {
429   absl::FlushLogSinks();
430 
431   if (data_->fail_quietly) {
432     FailQuietly();
433   } else {
434     FailWithoutStackTrace();
435   }
436 }
437 
SendToLog()438 void LogMessage::SendToLog() {
439   if (IsFatal()) PrepareToDie();
440   // Also log to all registered sinks, even if OnlyLogToStderr() is set.
441   log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
442                            data_->extra_sinks_only);
443   if (IsFatal()) Die();
444 }
445 
LogBacktraceIfNeeded()446 void LogMessage::LogBacktraceIfNeeded() {
447   if (!absl::log_internal::IsInitialized()) return;
448 
449   if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
450                                                 data_->entry.source_line()))
451     return;
452   stream_ << " (stacktrace:\n";
453   debugging_internal::DumpStackTrace(
454       1, log_internal::MaxFramesInLogStackTrace(),
455       log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream, &stream_);
456   stream_ << ") ";
457 }
458 
LogMessageFatal(const char * file,int line)459 LogMessageFatal::LogMessageFatal(const char* file, int line)
460     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
461 
LogMessageFatal(const char * file,int line,absl::string_view failure_msg)462 LogMessageFatal::LogMessageFatal(const char* file, int line,
463                                  absl::string_view failure_msg)
464     : LogMessage(file, line, absl::LogSeverity::kFatal) {
465   *this << "Check failed: " << failure_msg << " ";
466 }
467 
468 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
469 // disable msvc's warning about the d'tor never returning.
470 #ifdef _MSC_VER
471 #pragma warning(push)
472 #pragma warning(disable : 4722)
473 #endif
~LogMessageFatal()474 LogMessageFatal::~LogMessageFatal() {
475   Flush();
476   FailWithoutStackTrace();
477 }
478 #ifdef _MSC_VER
479 #pragma warning(pop)
480 #endif
481 
LogMessageQuietlyFatal(const char * file,int line)482 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
483     : LogMessage(file, line, absl::LogSeverity::kFatal) {
484   SetFailQuietly();
485 }
486 
LogMessageQuietlyFatal(const char * file,int line,absl::string_view failure_msg)487 LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
488                                                absl::string_view failure_msg)
489     : LogMessage(file, line, absl::LogSeverity::kFatal) {
490   SetFailQuietly();
491   *this << "Check failed: " << failure_msg << " ";
492 }
493 
494 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
495 // disable msvc's warning about the d'tor never returning.
496 #ifdef _MSC_VER
497 #pragma warning(push)
498 #pragma warning(disable : 4722)
499 #endif
~LogMessageQuietlyFatal()500 LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
501   Flush();
502   FailQuietly();
503 }
504 #ifdef _MSC_VER
505 #pragma warning(pop)
506 #endif
507 
508 }  // namespace log_internal
509 
510 ABSL_NAMESPACE_END
511 }  // namespace absl
512