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