globals.cc (4923B)
1 // Copyright 2022 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/log/internal/globals.h" 16 17 #include <atomic> 18 #include <cstdio> 19 20 #if defined(__EMSCRIPTEN__) 21 #include <emscripten/console.h> 22 #endif 23 24 #include "absl/base/attributes.h" 25 #include "absl/base/config.h" 26 #include "absl/base/internal/raw_logging.h" 27 #include "absl/base/log_severity.h" 28 #include "absl/strings/string_view.h" 29 #include "absl/strings/strip.h" 30 #include "absl/time/time.h" 31 32 namespace absl { 33 ABSL_NAMESPACE_BEGIN 34 namespace log_internal { 35 36 namespace { 37 // Keeps track of whether Logging initialization is finalized. 38 // Log messages generated before that will go to stderr. 39 ABSL_CONST_INIT std::atomic<bool> logging_initialized(false); 40 41 // The TimeZone used for logging. This may only be set once. 42 ABSL_CONST_INIT std::atomic<absl::TimeZone*> timezone_ptr{nullptr}; 43 44 // If true, the logging library will symbolize stack in fatal messages 45 ABSL_CONST_INIT std::atomic<bool> symbolize_stack_trace(true); 46 47 // Specifies maximum number of stack frames to report in fatal messages. 48 ABSL_CONST_INIT std::atomic<int> max_frames_in_stack_trace(64); 49 50 ABSL_CONST_INIT std::atomic<bool> exit_on_dfatal(true); 51 ABSL_CONST_INIT std::atomic<bool> suppress_sigabort_trace(false); 52 } // namespace 53 54 bool IsInitialized() { 55 return logging_initialized.load(std::memory_order_acquire); 56 } 57 58 void SetInitialized() { 59 logging_initialized.store(true, std::memory_order_release); 60 } 61 62 void WriteToStderr(absl::string_view message, absl::LogSeverity severity) { 63 if (message.empty()) return; 64 #if defined(__EMSCRIPTEN__) 65 // In WebAssembly, bypass filesystem emulation via fwrite. 66 // Skip a trailing newline character as emscripten_errn adds one itself. 67 const auto message_minus_newline = absl::StripSuffix(message, "\n"); 68 // emscripten_errn was introduced in 3.1.41 but broken in standalone mode 69 // until 3.1.43. 70 #if ABSL_INTERNAL_EMSCRIPTEN_VERSION >= 3001043 71 emscripten_errn(message_minus_newline.data(), message_minus_newline.size()); 72 #else 73 std::string null_terminated_message(message_minus_newline); 74 _emscripten_err(null_terminated_message.c_str()); 75 #endif 76 #else 77 // Avoid using std::cerr from this module since we may get called during 78 // exit code, and cerr may be partially or fully destroyed by then. 79 std::fwrite(message.data(), message.size(), 1, stderr); 80 #endif 81 82 #if defined(_WIN64) || defined(_WIN32) || defined(_WIN16) 83 // C99 requires stderr to not be fully-buffered by default (7.19.3.7), but 84 // MS CRT buffers it anyway, so we must `fflush` to ensure the string hits 85 // the console/file before the program dies (and takes the libc buffers 86 // with it). 87 // https://docs.microsoft.com/en-us/cpp/c-runtime-library/stream-i-o 88 if (severity >= absl::LogSeverity::kWarning) { 89 std::fflush(stderr); 90 } 91 #else 92 // Avoid unused parameter warning in this branch. 93 (void)severity; 94 #endif 95 } 96 97 void SetTimeZone(absl::TimeZone tz) { 98 absl::TimeZone* expected = nullptr; 99 absl::TimeZone* new_tz = new absl::TimeZone(tz); 100 // timezone_ptr can only be set once, otherwise new_tz is leaked. 101 if (!timezone_ptr.compare_exchange_strong(expected, new_tz, 102 std::memory_order_release, 103 std::memory_order_relaxed)) { 104 ABSL_RAW_LOG(FATAL, 105 "absl::log_internal::SetTimeZone() has already been called"); 106 } 107 } 108 109 const absl::TimeZone* TimeZone() { 110 return timezone_ptr.load(std::memory_order_acquire); 111 } 112 113 bool ShouldSymbolizeLogStackTrace() { 114 return symbolize_stack_trace.load(std::memory_order_acquire); 115 } 116 117 void EnableSymbolizeLogStackTrace(bool on_off) { 118 symbolize_stack_trace.store(on_off, std::memory_order_release); 119 } 120 121 int MaxFramesInLogStackTrace() { 122 return max_frames_in_stack_trace.load(std::memory_order_acquire); 123 } 124 125 void SetMaxFramesInLogStackTrace(int max_num_frames) { 126 max_frames_in_stack_trace.store(max_num_frames, std::memory_order_release); 127 } 128 129 bool ExitOnDFatal() { return exit_on_dfatal.load(std::memory_order_acquire); } 130 131 void SetExitOnDFatal(bool on_off) { 132 exit_on_dfatal.store(on_off, std::memory_order_release); 133 } 134 135 bool SuppressSigabortTrace() { 136 return suppress_sigabort_trace.load(std::memory_order_acquire); 137 } 138 139 bool SetSuppressSigabortTrace(bool on_off) { 140 return suppress_sigabort_trace.exchange(on_off); 141 } 142 143 } // namespace log_internal 144 ABSL_NAMESPACE_END 145 } // namespace absl