Coverage Report

Created: 2025-10-09 07:07

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