Coverage Report

Created: 2024-09-23 06:29

/src/abseil-cpp/absl/log/internal/log_message.cc
Line
Count
Source (jump to first uncovered line)
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 <ios>
31
#include <memory>
32
#include <ostream>
33
#include <string>
34
#include <tuple>
35
36
#include "absl/base/attributes.h"
37
#include "absl/base/config.h"
38
#include "absl/base/internal/raw_logging.h"
39
#include "absl/base/internal/strerror.h"
40
#include "absl/base/internal/sysinfo.h"
41
#include "absl/base/log_severity.h"
42
#include "absl/container/inlined_vector.h"
43
#include "absl/debugging/internal/examine_stack.h"
44
#include "absl/log/globals.h"
45
#include "absl/log/internal/append_truncated.h"
46
#include "absl/log/internal/globals.h"
47
#include "absl/log/internal/log_format.h"
48
#include "absl/log/internal/log_sink_set.h"
49
#include "absl/log/internal/proto.h"
50
#include "absl/log/log_entry.h"
51
#include "absl/log/log_sink.h"
52
#include "absl/log/log_sink_registry.h"
53
#include "absl/memory/memory.h"
54
#include "absl/strings/string_view.h"
55
#include "absl/time/clock.h"
56
#include "absl/time/time.h"
57
#include "absl/types/span.h"
58
59
extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
60
0
    AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
61
  // Default - Do nothing
62
0
}
63
64
namespace absl {
65
ABSL_NAMESPACE_BEGIN
66
namespace log_internal {
67
68
namespace {
69
// message `logging.proto.Event`
70
enum EventTag : uint8_t {
71
  kFileName = 2,
72
  kFileLine = 3,
73
  kTimeNsecs = 4,
74
  kSeverity = 5,
75
  kThreadId = 6,
76
  kValue = 7,
77
  kSequenceNumber = 9,
78
  kThreadName = 10,
79
};
80
81
// message `logging.proto.Value`
82
enum ValueTag : uint8_t {
83
  kString = 1,
84
  kStringLiteral = 6,
85
};
86
87
// Decodes a `logging.proto.Value` from `buf` and writes a string representation
88
// into `dst`.  The string representation will be truncated if `dst` is not
89
// large enough to hold it.  Returns false if `dst` has size zero or one (i.e.
90
// sufficient only for a nul-terminator) and no decoded data could be written.
91
// This function may or may not write a nul-terminator into `dst`, and it may or
92
// may not truncate the data it writes in order to do make space for that nul
93
// terminator.  In any case, `dst` will be advanced to point at the byte where
94
// subsequent writes should begin.
95
6.35M
bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
96
6.35M
  if (dst.size() <= 1) return false;
97
6.35M
  ProtoField field;
98
12.7M
  while (field.DecodeFrom(&buf)) {
99
6.35M
    switch (field.tag()) {
100
2.56M
      case ValueTag::kString:
101
6.35M
      case ValueTag::kStringLiteral:
102
6.35M
        if (field.type() == WireType::kLengthDelimited)
103
6.35M
          if (log_internal::AppendTruncated(field.string_value(), dst) <
104
6.35M
              field.string_value().size())
105
0
            return false;
106
6.35M
    }
107
6.35M
  }
108
6.35M
  return true;
109
6.35M
}
110
111
// See `logging.proto.Severity`
112
3.79M
int32_t ProtoSeverity(absl::LogSeverity severity, int verbose_level) {
113
3.79M
  switch (severity) {
114
0
    case absl::LogSeverity::kInfo:
115
0
      if (verbose_level == absl::LogEntry::kNoVerbosityLevel) return 800;
116
0
      return 600 - verbose_level;
117
1.23M
    case absl::LogSeverity::kWarning:
118
1.23M
      return 900;
119
2.56M
    case absl::LogSeverity::kError:
120
2.56M
      return 950;
121
0
    case absl::LogSeverity::kFatal:
122
0
      return 1100;
123
0
    default:
124
0
      return 800;
125
3.79M
  }
126
3.79M
}
127
128
3.79M
absl::string_view Basename(absl::string_view filepath) {
129
#ifdef _WIN32
130
  size_t path = filepath.find_last_of("/\\");
131
#else
132
3.79M
  size_t path = filepath.find_last_of('/');
133
3.79M
#endif
134
3.79M
  if (path != filepath.npos) filepath.remove_prefix(path + 1);
135
3.79M
  return filepath;
136
3.79M
}
137
138
0
void WriteToString(const char* data, void* str) {
139
0
  reinterpret_cast<std::string*>(str)->append(data);
140
0
}
141
0
void WriteToStream(const char* data, void* os) {
142
0
  auto* cast_os = static_cast<std::ostream*>(os);
143
0
  *cast_os << data;
144
0
}
145
}  // namespace
146
147
struct LogMessage::LogMessageData final {
148
  LogMessageData(const char* file, int line, absl::LogSeverity severity,
149
                 absl::Time timestamp);
150
  LogMessageData(const LogMessageData&) = delete;
151
  LogMessageData& operator=(const LogMessageData&) = delete;
152
153
  // `LogEntry` sent to `LogSink`s; contains metadata.
154
  absl::LogEntry entry;
155
156
  // true => this was first fatal msg
157
  bool first_fatal;
158
  // true => all failures should be quiet
159
  bool fail_quietly;
160
  // true => PLOG was requested
161
  bool is_perror;
162
163
  // Extra `LogSink`s to log to, in addition to `global_sinks`.
164
  absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
165
  // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
166
  // non-sink targets (e.g. stderr, log files).
167
  bool extra_sinks_only;
168
169
  std::ostream manipulated;  // ostream with IO manipulators applied
170
171
  // A `logging.proto.Event` proto message is built into `encoded_buf`.
172
  std::array<char, kLogMessageBufferSize> encoded_buf;
173
  // `encoded_remaining()` is the suffix of `encoded_buf` that has not been
174
  // filled yet.  If a datum to be encoded does not fit into
175
  // `encoded_remaining()` and cannot be truncated to fit, the size of
176
  // `encoded_remaining()` will be zeroed to prevent encoding of any further
177
  // data.  Note that in this case its `data()` pointer will not point past the
178
  // end of `encoded_buf`.
179
  // The first use of `encoded_remaining()` is our chance to record metadata
180
  // after any modifications (e.g. by `AtLocation()`) but before any data have
181
  // been recorded.  We want to record metadata before data so that data are
182
  // preferentially truncated if we run out of buffer.
183
39.2M
  absl::Span<char>& encoded_remaining() {
184
39.2M
    if (encoded_remaining_actual_do_not_use_directly.data() == nullptr) {
185
3.79M
      encoded_remaining_actual_do_not_use_directly =
186
3.79M
          absl::MakeSpan(encoded_buf);
187
3.79M
      InitializeEncodingAndFormat();
188
3.79M
    }
189
39.2M
    return encoded_remaining_actual_do_not_use_directly;
190
39.2M
  }
191
  absl::Span<char> encoded_remaining_actual_do_not_use_directly;
192
193
  // A formatted string message is built in `string_buf`.
194
  std::array<char, kLogMessageBufferSize> string_buf;
195
196
  void InitializeEncodingAndFormat();
197
  void FinalizeEncodingAndFormat();
198
};
199
200
LogMessage::LogMessageData::LogMessageData(const char* file, int line,
201
                                           absl::LogSeverity severity,
202
                                           absl::Time timestamp)
203
3.79M
    : extra_sinks_only(false), manipulated(nullptr) {
204
  // Legacy defaults for LOG's ostream:
205
3.79M
  manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
206
3.79M
  entry.full_filename_ = file;
207
3.79M
  entry.base_filename_ = Basename(file);
208
3.79M
  entry.line_ = line;
209
3.79M
  entry.prefix_ = absl::ShouldPrependLogPrefix();
210
3.79M
  entry.severity_ = absl::NormalizeLogSeverity(severity);
211
3.79M
  entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
212
3.79M
  entry.timestamp_ = timestamp;
213
3.79M
  entry.tid_ = absl::base_internal::GetCachedTID();
214
3.79M
}
215
216
3.79M
void LogMessage::LogMessageData::InitializeEncodingAndFormat() {
217
3.79M
  EncodeStringTruncate(EventTag::kFileName, entry.source_filename(),
218
3.79M
                       &encoded_remaining());
219
3.79M
  EncodeVarint(EventTag::kFileLine, entry.source_line(), &encoded_remaining());
220
3.79M
  EncodeVarint(EventTag::kTimeNsecs, absl::ToUnixNanos(entry.timestamp()),
221
3.79M
               &encoded_remaining());
222
3.79M
  EncodeVarint(EventTag::kSeverity,
223
3.79M
               ProtoSeverity(entry.log_severity(), entry.verbosity()),
224
3.79M
               &encoded_remaining());
225
3.79M
  EncodeVarint(EventTag::kThreadId, entry.tid(), &encoded_remaining());
226
3.79M
}
227
228
3.79M
void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
229
  // Note that `encoded_remaining()` may have zero size without pointing past
230
  // the end of `encoded_buf`, so the difference between `data()` pointers is
231
  // used to compute the size of `encoded_data`.
232
3.79M
  absl::Span<const char> encoded_data(
233
3.79M
      encoded_buf.data(),
234
3.79M
      static_cast<size_t>(encoded_remaining().data() - encoded_buf.data()));
235
  // `string_remaining` is the suffix of `string_buf` that has not been filled
236
  // yet.
237
3.79M
  absl::Span<char> string_remaining(string_buf);
238
  // We may need to write a newline and nul-terminator at the end of the decoded
239
  // string data.  Rather than worry about whether those should overwrite the
240
  // end of the string (if the buffer is full) or be appended, we avoid writing
241
  // into the last two bytes so we always have space to append.
242
3.79M
  string_remaining.remove_suffix(2);
243
3.79M
  entry.prefix_len_ =
244
3.79M
      entry.prefix() ? log_internal::FormatLogPrefix(
245
3.79M
                           entry.log_severity(), entry.timestamp(), entry.tid(),
246
3.79M
                           entry.source_basename(), entry.source_line(),
247
3.79M
                           log_internal::ThreadIsLoggingToLogSink()
248
3.79M
                               ? PrefixFormat::kRaw
249
3.79M
                               : PrefixFormat::kNotRaw,
250
3.79M
                           string_remaining)
251
3.79M
                     : 0;
252
  // Decode data from `encoded_buf` until we run out of data or we run out of
253
  // `string_remaining`.
254
3.79M
  ProtoField field;
255
29.1M
  while (field.DecodeFrom(&encoded_data)) {
256
25.3M
    switch (field.tag()) {
257
6.35M
      case EventTag::kValue:
258
6.35M
        if (field.type() != WireType::kLengthDelimited) continue;
259
6.35M
        if (PrintValue(string_remaining, field.bytes_value())) continue;
260
0
        break;
261
25.3M
    }
262
25.3M
  }
263
3.79M
  auto chars_written =
264
3.79M
      static_cast<size_t>(string_remaining.data() - string_buf.data());
265
3.79M
    string_buf[chars_written++] = '\n';
266
3.79M
  string_buf[chars_written++] = '\0';
267
3.79M
  entry.text_message_with_prefix_and_newline_and_nul_ =
268
3.79M
      absl::MakeSpan(string_buf).subspan(0, chars_written);
269
3.79M
}
270
271
LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
272
    : data_(absl::make_unique<LogMessageData>(file, line, severity,
273
3.79M
                                              absl::Now())) {
274
3.79M
  data_->first_fatal = false;
275
3.79M
  data_->is_perror = false;
276
3.79M
  data_->fail_quietly = false;
277
278
  // This logs a backtrace even if the location is subsequently changed using
279
  // AtLocation.  This quirk, and the behavior when AtLocation is called twice,
280
  // are fixable but probably not worth fixing.
281
3.79M
  LogBacktraceIfNeeded();
282
3.79M
}
283
284
LogMessage::LogMessage(const char* file, int line, InfoTag)
285
0
    : LogMessage(file, line, absl::LogSeverity::kInfo) {}
286
LogMessage::LogMessage(const char* file, int line, WarningTag)
287
1.23M
    : LogMessage(file, line, absl::LogSeverity::kWarning) {}
288
LogMessage::LogMessage(const char* file, int line, ErrorTag)
289
2.56M
    : LogMessage(file, line, absl::LogSeverity::kError) {}
290
291
3.79M
LogMessage::~LogMessage() {
292
#ifdef ABSL_MIN_LOG_LEVEL
293
  if (data_->entry.log_severity() <
294
          static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
295
      data_->entry.log_severity() < absl::LogSeverity::kFatal) {
296
    return;
297
  }
298
#endif
299
3.79M
  Flush();
300
3.79M
}
301
302
0
LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
303
0
  data_->entry.full_filename_ = file;
304
0
  data_->entry.base_filename_ = Basename(file);
305
0
  data_->entry.line_ = line;
306
0
  LogBacktraceIfNeeded();
307
0
  return *this;
308
0
}
309
310
0
LogMessage& LogMessage::NoPrefix() {
311
0
  data_->entry.prefix_ = false;
312
0
  return *this;
313
0
}
314
315
0
LogMessage& LogMessage::WithVerbosity(int verbose_level) {
316
0
  if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
317
0
    data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
318
0
  } else {
319
0
    data_->entry.verbose_level_ = std::max(0, verbose_level);
320
0
  }
321
0
  return *this;
322
0
}
323
324
0
LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
325
0
  data_->entry.timestamp_ = timestamp;
326
0
  return *this;
327
0
}
328
329
0
LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
330
0
  data_->entry.tid_ = tid;
331
0
  return *this;
332
0
}
333
334
0
LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
335
0
  data_->entry.full_filename_ = entry.full_filename_;
336
0
  data_->entry.base_filename_ = entry.base_filename_;
337
0
  data_->entry.line_ = entry.line_;
338
0
  data_->entry.prefix_ = entry.prefix_;
339
0
  data_->entry.severity_ = entry.severity_;
340
0
  data_->entry.verbose_level_ = entry.verbose_level_;
341
0
  data_->entry.timestamp_ = entry.timestamp_;
342
0
  data_->entry.tid_ = entry.tid_;
343
0
  return *this;
344
0
}
345
346
0
LogMessage& LogMessage::WithPerror() {
347
0
  data_->is_perror = true;
348
0
  return *this;
349
0
}
350
351
0
LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
352
0
  ABSL_INTERNAL_CHECK(sink, "null LogSink*");
353
0
  data_->extra_sinks.push_back(sink);
354
0
  return *this;
355
0
}
356
357
0
LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
358
0
  ABSL_INTERNAL_CHECK(sink, "null LogSink*");
359
0
  data_->extra_sinks.clear();
360
0
  data_->extra_sinks.push_back(sink);
361
0
  data_->extra_sinks_only = true;
362
0
  return *this;
363
0
}
364
365
#ifdef __ELF__
366
extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
367
extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
368
#endif
369
370
0
void LogMessage::FailWithoutStackTrace() {
371
  // Now suppress repeated trace logging:
372
0
  log_internal::SetSuppressSigabortTrace(true);
373
#if defined _DEBUG && defined COMPILER_MSVC
374
  // When debugging on windows, avoid the obnoxious dialog.
375
  __debugbreak();
376
#endif
377
378
0
#ifdef __ELF__
379
  // For b/8737634, flush coverage if we are in coverage mode.
380
0
  if (&__gcov_dump != nullptr) {
381
0
    __gcov_dump();
382
0
  } else if (&__gcov_flush != nullptr) {
383
0
    __gcov_flush();
384
0
  }
385
0
#endif
386
387
0
  abort();
388
0
}
389
390
0
void LogMessage::FailQuietly() {
391
  // _exit. Calling abort() would trigger all sorts of death signal handlers
392
  // and a detailed stack trace. Calling exit() would trigger the onexit
393
  // handlers, including the heap-leak checker, which is guaranteed to fail in
394
  // this case: we probably just new'ed the std::string that we logged.
395
  // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
396
  // of the program quickly, and it doesn't make much sense for FailQuietly to
397
  // offer different guarantees about exit behavior than Fail does. (And as a
398
  // consequence for QCHECK and CHECK to offer different exit behaviors)
399
0
  _exit(1);
400
0
}
401
402
0
LogMessage& LogMessage::operator<<(const std::string& v) {
403
0
  CopyToEncodedBuffer<StringType::kNotLiteral>(v);
404
0
  return *this;
405
0
}
406
407
0
LogMessage& LogMessage::operator<<(absl::string_view v) {
408
0
  CopyToEncodedBuffer<StringType::kNotLiteral>(v);
409
0
  return *this;
410
0
}
411
0
LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
412
0
  OstreamView view(*data_);
413
0
  data_->manipulated << m;
414
0
  return *this;
415
0
}
416
0
LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
417
0
  OstreamView view(*data_);
418
0
  data_->manipulated << m;
419
0
  return *this;
420
0
}
421
template LogMessage& LogMessage::operator<<(const char& v);
422
template LogMessage& LogMessage::operator<<(const signed char& v);
423
template LogMessage& LogMessage::operator<<(const unsigned char& v);
424
template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
425
template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
426
template LogMessage& LogMessage::operator<<(const int& v);
427
template LogMessage& LogMessage::operator<<(const unsigned int& v);
428
template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
429
template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
430
template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
431
template LogMessage& LogMessage::operator<<(
432
    const unsigned long long& v);  // NOLINT
433
template LogMessage& LogMessage::operator<<(void* const& v);
434
template LogMessage& LogMessage::operator<<(const void* const& v);
435
template LogMessage& LogMessage::operator<<(const float& v);
436
template LogMessage& LogMessage::operator<<(const double& v);
437
template LogMessage& LogMessage::operator<<(const bool& v);
438
439
3.79M
void LogMessage::Flush() {
440
3.79M
  if (data_->entry.log_severity() < absl::MinLogLevel()) return;
441
442
3.79M
  if (data_->is_perror) {
443
0
    InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
444
0
                     << " [" << errno_saver_() << "]";
445
0
  }
446
447
  // Have we already seen a fatal message?
448
3.79M
  ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);
449
3.79M
  if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
450
3.79M
      absl::log_internal::ExitOnDFatal()) {
451
    // Exactly one LOG(FATAL) message is responsible for aborting the process,
452
    // even if multiple threads LOG(FATAL) concurrently.
453
0
    bool expected_seen_fatal = false;
454
0
    if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,
455
0
                                           std::memory_order_relaxed)) {
456
0
      data_->first_fatal = true;
457
0
    }
458
0
  }
459
460
3.79M
  data_->FinalizeEncodingAndFormat();
461
3.79M
  data_->entry.encoding_ =
462
3.79M
      absl::string_view(data_->encoded_buf.data(),
463
3.79M
                        static_cast<size_t>(data_->encoded_remaining().data() -
464
3.79M
                                            data_->encoded_buf.data()));
465
3.79M
  SendToLog();
466
3.79M
}
467
468
0
void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
469
470
LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
471
2.56M
    : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining()) {
472
  // This constructor sets the `streambuf` up so that streaming into an attached
473
  // ostream encodes string data in-place.  To do that, we write appropriate
474
  // headers into the buffer using a copy of the buffer view so that we can
475
  // decide not to keep them later if nothing is ever streamed in.  We don't
476
  // know how much data we'll get, but we can use the size of the remaining
477
  // buffer as an upper bound and fill in the right size once we know it.
478
2.56M
  message_start_ =
479
2.56M
      EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),
480
2.56M
                         &encoded_remaining_copy_);
481
2.56M
  string_start_ =
482
2.56M
      EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
483
2.56M
                         &encoded_remaining_copy_);
484
2.56M
  setp(encoded_remaining_copy_.data(),
485
2.56M
       encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
486
2.56M
  data_.manipulated.rdbuf(this);
487
2.56M
}
488
489
2.56M
LogMessage::OstreamView::~OstreamView() {
490
2.56M
  data_.manipulated.rdbuf(nullptr);
491
2.56M
  if (!string_start_.data()) {
492
    // The second field header didn't fit.  Whether the first one did or not, we
493
    // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
494
    // size of `data_->encoded_remaining()` so that no more data are encoded.
495
0
    data_.encoded_remaining().remove_suffix(data_.encoded_remaining().size());
496
0
    return;
497
0
  }
498
2.56M
  const absl::Span<const char> contents(pbase(),
499
2.56M
                                        static_cast<size_t>(pptr() - pbase()));
500
2.56M
  if (contents.empty()) return;
501
2.56M
  encoded_remaining_copy_.remove_prefix(contents.size());
502
2.56M
  EncodeMessageLength(string_start_, &encoded_remaining_copy_);
503
2.56M
  EncodeMessageLength(message_start_, &encoded_remaining_copy_);
504
2.56M
  data_.encoded_remaining() = encoded_remaining_copy_;
505
2.56M
}
506
507
2.56M
std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
508
509
7.58M
bool LogMessage::IsFatal() const {
510
7.58M
  return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
511
7.58M
         absl::log_internal::ExitOnDFatal();
512
7.58M
}
513
514
0
void LogMessage::PrepareToDie() {
515
  // If we log a FATAL message, flush all the log destinations, then toss
516
  // a signal for others to catch. We leave the logs in a state that
517
  // someone else can use them (as long as they flush afterwards)
518
0
  if (data_->first_fatal) {
519
    // Notify observers about the upcoming fatal error.
520
0
    ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
521
0
  }
522
523
0
  if (!data_->fail_quietly) {
524
    // Log the message first before we start collecting stack trace.
525
0
    log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
526
0
                             data_->extra_sinks_only);
527
528
    // `DumpStackTrace` generates an empty string under MSVC.
529
    // Adding the constant prefix here simplifies testing.
530
0
    data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
531
0
    debugging_internal::DumpStackTrace(
532
0
        0, log_internal::MaxFramesInLogStackTrace(),
533
0
        log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
534
0
        &data_->entry.stacktrace_);
535
0
  }
536
0
}
537
538
0
void LogMessage::Die() {
539
0
  absl::FlushLogSinks();
540
541
0
  if (data_->fail_quietly) {
542
0
    FailQuietly();
543
0
  } else {
544
0
    FailWithoutStackTrace();
545
0
  }
546
0
}
547
548
3.79M
void LogMessage::SendToLog() {
549
3.79M
  if (IsFatal()) PrepareToDie();
550
  // Also log to all registered sinks, even if OnlyLogToStderr() is set.
551
3.79M
  log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
552
3.79M
                           data_->extra_sinks_only);
553
3.79M
  if (IsFatal()) Die();
554
3.79M
}
555
556
3.79M
void LogMessage::LogBacktraceIfNeeded() {
557
3.79M
  if (!absl::log_internal::IsInitialized()) return;
558
559
0
  if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
560
0
                                                data_->entry.source_line()))
561
0
    return;
562
0
  OstreamView view(*data_);
563
0
  view.stream() << " (stacktrace:\n";
564
0
  debugging_internal::DumpStackTrace(
565
0
      1, log_internal::MaxFramesInLogStackTrace(),
566
0
      log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,
567
0
      &view.stream());
568
0
  view.stream() << ") ";
569
0
}
570
571
// Encodes into `data_->encoded_remaining()` a partial `logging.proto.Event`
572
// containing the specified string data using a `Value` field appropriate to
573
// `str_type`.  Truncates `str` if necessary, but emits nothing and marks the
574
// buffer full if  even the field headers do not fit.
575
template <LogMessage::StringType str_type>
576
3.79M
void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
577
3.79M
  auto encoded_remaining_copy = data_->encoded_remaining();
578
3.79M
  auto start = EncodeMessageStart(
579
3.79M
      EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
580
3.79M
      &encoded_remaining_copy);
581
  // If the `logging.proto.Event.value` field header did not fit,
582
  // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
583
  // `EncodeStringTruncate` will fail too.
584
3.79M
  if (EncodeStringTruncate(str_type == StringType::kLiteral
585
3.79M
                               ? ValueTag::kStringLiteral
586
3.79M
                               : ValueTag::kString,
587
3.79M
                           str, &encoded_remaining_copy)) {
588
    // The string may have been truncated, but the field header fit.
589
3.79M
    EncodeMessageLength(start, &encoded_remaining_copy);
590
3.79M
    data_->encoded_remaining() = encoded_remaining_copy;
591
3.79M
  } else {
592
    // The field header(s) did not fit; zero `encoded_remaining()` so we don't
593
    // write anything else later.
594
0
    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
595
0
  }
596
3.79M
}
void absl::log_internal::LogMessage::CopyToEncodedBuffer<(absl::log_internal::LogMessage::StringType)0>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
576
3.79M
void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
577
3.79M
  auto encoded_remaining_copy = data_->encoded_remaining();
578
3.79M
  auto start = EncodeMessageStart(
579
3.79M
      EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
580
3.79M
      &encoded_remaining_copy);
581
  // If the `logging.proto.Event.value` field header did not fit,
582
  // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
583
  // `EncodeStringTruncate` will fail too.
584
3.79M
  if (EncodeStringTruncate(str_type == StringType::kLiteral
585
3.79M
                               ? ValueTag::kStringLiteral
586
3.79M
                               : ValueTag::kString,
587
3.79M
                           str, &encoded_remaining_copy)) {
588
    // The string may have been truncated, but the field header fit.
589
3.79M
    EncodeMessageLength(start, &encoded_remaining_copy);
590
3.79M
    data_->encoded_remaining() = encoded_remaining_copy;
591
3.79M
  } else {
592
    // The field header(s) did not fit; zero `encoded_remaining()` so we don't
593
    // write anything else later.
594
0
    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
595
0
  }
596
3.79M
}
Unexecuted instantiation: void absl::log_internal::LogMessage::CopyToEncodedBuffer<(absl::log_internal::LogMessage::StringType)1>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
597
template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
598
    absl::string_view str);
599
template void LogMessage::CopyToEncodedBuffer<
600
    LogMessage::StringType::kNotLiteral>(absl::string_view str);
601
template <LogMessage::StringType str_type>
602
0
void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
603
0
  auto encoded_remaining_copy = data_->encoded_remaining();
604
0
  auto value_start = EncodeMessageStart(
605
0
      EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
606
0
      &encoded_remaining_copy);
607
0
  auto str_start = EncodeMessageStart(str_type == StringType::kLiteral
608
0
                                          ? ValueTag::kStringLiteral
609
0
                                          : ValueTag::kString,
610
0
                                      num, &encoded_remaining_copy);
611
0
  if (str_start.data()) {
612
    // The field headers fit.
613
0
    log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
614
0
    EncodeMessageLength(str_start, &encoded_remaining_copy);
615
0
    EncodeMessageLength(value_start, &encoded_remaining_copy);
616
0
    data_->encoded_remaining() = encoded_remaining_copy;
617
0
  } else {
618
    // The field header(s) did not fit; zero `encoded_remaining()` so we don't
619
    // write anything else later.
620
0
    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
621
0
  }
622
0
}
Unexecuted instantiation: void absl::log_internal::LogMessage::CopyToEncodedBuffer<(absl::log_internal::LogMessage::StringType)0>(char, unsigned long)
Unexecuted instantiation: void absl::log_internal::LogMessage::CopyToEncodedBuffer<(absl::log_internal::LogMessage::StringType)1>(char, unsigned long)
623
template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
624
    char ch, size_t num);
625
template void LogMessage::CopyToEncodedBuffer<
626
    LogMessage::StringType::kNotLiteral>(char ch, size_t num);
627
628
// We intentionally don't return from these destructors. Disable MSVC's warning
629
// about the destructor never returning as we do so intentionally here.
630
#if defined(_MSC_VER) && !defined(__clang__)
631
#pragma warning(push)
632
#pragma warning(disable : 4722)
633
#endif
634
635
LogMessageFatal::LogMessageFatal(const char* file, int line)
636
0
    : LogMessage(file, line, absl::LogSeverity::kFatal) {}
637
638
LogMessageFatal::LogMessageFatal(const char* file, int line,
639
                                 absl::string_view failure_msg)
640
0
    : LogMessage(file, line, absl::LogSeverity::kFatal) {
641
0
  *this << "Check failed: " << failure_msg << " ";
642
0
}
643
644
0
LogMessageFatal::~LogMessageFatal() {
645
0
  Flush();
646
0
  FailWithoutStackTrace();
647
0
}
648
649
LogMessageDebugFatal::LogMessageDebugFatal(const char* file, int line)
650
0
    : LogMessage(file, line, absl::LogSeverity::kFatal) {}
651
652
0
LogMessageDebugFatal::~LogMessageDebugFatal() {
653
0
  Flush();
654
0
  FailWithoutStackTrace();
655
0
}
656
657
LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal(const char* file,
658
                                                         int line)
659
0
    : LogMessage(file, line, absl::LogSeverity::kFatal) {
660
0
  SetFailQuietly();
661
0
}
662
663
0
LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() {
664
0
  Flush();
665
0
  FailQuietly();
666
0
}
667
668
LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
669
0
    : LogMessage(file, line, absl::LogSeverity::kFatal) {
670
0
  SetFailQuietly();
671
0
}
672
673
LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
674
                                               absl::string_view failure_msg)
675
0
    : LogMessageQuietlyFatal(file, line) {
676
0
    *this << "Check failed: " << failure_msg << " ";
677
0
}
678
679
0
LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
680
0
  Flush();
681
0
  FailQuietly();
682
0
}
683
#if defined(_MSC_VER) && !defined(__clang__)
684
#pragma warning(pop)
685
#endif
686
687
}  // namespace log_internal
688
689
ABSL_NAMESPACE_END
690
}  // namespace absl