xref: /aosp_15_r20/external/cronet/base/logging.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #ifdef BASE_CHECK_H_
8*6777b538SAndroid Build Coastguard Worker #error "logging.h should not include check.h"
9*6777b538SAndroid Build Coastguard Worker #endif
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <limits.h>
12*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include <algorithm>
15*6777b538SAndroid Build Coastguard Worker #include <atomic>
16*6777b538SAndroid Build Coastguard Worker #include <cstring>
17*6777b538SAndroid Build Coastguard Worker #include <ctime>
18*6777b538SAndroid Build Coastguard Worker #include <iomanip>
19*6777b538SAndroid Build Coastguard Worker #include <memory>
20*6777b538SAndroid Build Coastguard Worker #include <ostream>
21*6777b538SAndroid Build Coastguard Worker #include <string>
22*6777b538SAndroid Build Coastguard Worker #include <tuple>
23*6777b538SAndroid Build Coastguard Worker #include <utility>
24*6777b538SAndroid Build Coastguard Worker #include <vector>
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/base_switches.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/containers/stack.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/debug/alias.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/debug/crash_logging.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/debug/debugger.h"
33*6777b538SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
34*6777b538SAndroid Build Coastguard Worker #include "base/debug/task_trace.h"
35*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
36*6777b538SAndroid Build Coastguard Worker #include "base/immediate_crash.h"
37*6777b538SAndroid Build Coastguard Worker #include "base/no_destructor.h"
38*6777b538SAndroid Build Coastguard Worker #include "base/not_fatal_until.h"
39*6777b538SAndroid Build Coastguard Worker #include "base/path_service.h"
40*6777b538SAndroid Build Coastguard Worker #include "base/pending_task.h"
41*6777b538SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
42*6777b538SAndroid Build Coastguard Worker #include "base/process/process_handle.h"
43*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
44*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
45*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
46*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
47*6777b538SAndroid Build Coastguard Worker #include "base/strings/sys_string_conversions.h"
48*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
49*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
50*6777b538SAndroid Build Coastguard Worker #include "base/task/common/task_annotator.h"
51*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_logging_settings.h"
52*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
53*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
54*6777b538SAndroid Build Coastguard Worker #include "base/vlog.h"
55*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
56*6777b538SAndroid Build Coastguard Worker #include "build/chromeos_buildflags.h"
57*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
60*6777b538SAndroid Build Coastguard Worker #include "base/auto_reset.h"
61*6777b538SAndroid Build Coastguard Worker #include "base/debug/crash_logging.h"
62*6777b538SAndroid Build Coastguard Worker #endif  // !BUILDFLAG(IS_NACL)
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker #if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL)
65*6777b538SAndroid Build Coastguard Worker #include "base/debug/leak_annotations.h"
66*6777b538SAndroid Build Coastguard Worker #endif  // defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL)
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
69*6777b538SAndroid Build Coastguard Worker #include <windows.h>
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker #include <io.h>
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker #include "base/win/win_util.h"
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker typedef HANDLE FileHandle;
76*6777b538SAndroid Build Coastguard Worker // Windows warns on using write().  It prefers _write().
77*6777b538SAndroid Build Coastguard Worker #define write(fd, buf, count) _write(fd, buf, static_cast<unsigned int>(count))
78*6777b538SAndroid Build Coastguard Worker // Windows doesn't define STDERR_FILENO.  Define it here.
79*6777b538SAndroid Build Coastguard Worker #define STDERR_FILENO 2
80*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
83*6777b538SAndroid Build Coastguard Worker #include <CoreFoundation/CoreFoundation.h>
84*6777b538SAndroid Build Coastguard Worker #include <mach-o/dyld.h>
85*6777b538SAndroid Build Coastguard Worker #include <mach/mach.h>
86*6777b538SAndroid Build Coastguard Worker #include <mach/mach_time.h>
87*6777b538SAndroid Build Coastguard Worker #include <os/log.h>
88*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_APPLE)
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
91*6777b538SAndroid Build Coastguard Worker #include <errno.h>
92*6777b538SAndroid Build Coastguard Worker #include <paths.h>
93*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
94*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
95*6777b538SAndroid Build Coastguard Worker #include <string.h>
96*6777b538SAndroid Build Coastguard Worker #include <sys/stat.h>
97*6777b538SAndroid Build Coastguard Worker #include <time.h>
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker #include "base/posix/safe_strerror.h"
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_NACL)
102*6777b538SAndroid Build Coastguard Worker #include <sys/time.h>  // timespec doesn't seem to be in <time.h>
103*6777b538SAndroid Build Coastguard Worker #endif
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker #define MAX_PATH PATH_MAX
106*6777b538SAndroid Build Coastguard Worker typedef FILE* FileHandle;
107*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
110*6777b538SAndroid Build Coastguard Worker #include <android/log.h>
111*6777b538SAndroid Build Coastguard Worker #include "base/android/jni_android.h"
112*6777b538SAndroid Build Coastguard Worker #endif
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS_ASH)
115*6777b538SAndroid Build Coastguard Worker #include "base/files/scoped_file.h"
116*6777b538SAndroid Build Coastguard Worker #endif
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
119*6777b538SAndroid Build Coastguard Worker #include "base/fuchsia/scoped_fx_logger.h"
120*6777b538SAndroid Build Coastguard Worker #endif
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker namespace logging {
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker namespace {
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker int g_min_log_level = 0;
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker // NOTE: Once |g_vlog_info| has been initialized, it might be in use
129*6777b538SAndroid Build Coastguard Worker // by another thread. Never delete the old VLogInfo, just create a second
130*6777b538SAndroid Build Coastguard Worker // one and overwrite. We need to use leak-san annotations on this intentional
131*6777b538SAndroid Build Coastguard Worker // leak.
132*6777b538SAndroid Build Coastguard Worker //
133*6777b538SAndroid Build Coastguard Worker // This can be read/written on multiple threads. In tests we don't see that
134*6777b538SAndroid Build Coastguard Worker // causing a problem as updates tend to happen early. Atomic ensures there are
135*6777b538SAndroid Build Coastguard Worker // no problems. To avoid some of the overhead of Atomic, we use
136*6777b538SAndroid Build Coastguard Worker // |load(std::memory_order_acquire)| and |store(...,
137*6777b538SAndroid Build Coastguard Worker // std::memory_order_release)| when reading or writing. This guarantees that the
138*6777b538SAndroid Build Coastguard Worker // referenced object is available at the time the |g_vlog_info| is read and that
139*6777b538SAndroid Build Coastguard Worker // |g_vlog_info| is updated atomically.
140*6777b538SAndroid Build Coastguard Worker //
141*6777b538SAndroid Build Coastguard Worker // Do not access this directly. You must use |GetVlogInfo|, |InitializeVlogInfo|
142*6777b538SAndroid Build Coastguard Worker // and/or |ExchangeVlogInfo|.
143*6777b538SAndroid Build Coastguard Worker std::atomic<VlogInfo*> g_vlog_info = nullptr;
144*6777b538SAndroid Build Coastguard Worker 
GetVlogInfo()145*6777b538SAndroid Build Coastguard Worker VlogInfo* GetVlogInfo() {
146*6777b538SAndroid Build Coastguard Worker   return g_vlog_info.load(std::memory_order_acquire);
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker // Sets g_vlog_info if it is not already set. Checking that it's not already set
150*6777b538SAndroid Build Coastguard Worker // prevents logging initialization (which can come late in test setup) from
151*6777b538SAndroid Build Coastguard Worker // overwriting values set via ScopedVmoduleSwitches.
InitializeVlogInfo(VlogInfo * vlog_info)152*6777b538SAndroid Build Coastguard Worker bool InitializeVlogInfo(VlogInfo* vlog_info) {
153*6777b538SAndroid Build Coastguard Worker   VlogInfo* previous_vlog_info = nullptr;
154*6777b538SAndroid Build Coastguard Worker   return g_vlog_info.compare_exchange_strong(previous_vlog_info, vlog_info);
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker 
ExchangeVlogInfo(VlogInfo * vlog_info)157*6777b538SAndroid Build Coastguard Worker VlogInfo* ExchangeVlogInfo(VlogInfo* vlog_info) {
158*6777b538SAndroid Build Coastguard Worker   return g_vlog_info.exchange(vlog_info);
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker 
161*6777b538SAndroid Build Coastguard Worker // Creates a VlogInfo from the commandline if it has been initialized and if it
162*6777b538SAndroid Build Coastguard Worker // contains relevant switches, otherwise this returns |nullptr|.
VlogInfoFromCommandLine()163*6777b538SAndroid Build Coastguard Worker std::unique_ptr<VlogInfo> VlogInfoFromCommandLine() {
164*6777b538SAndroid Build Coastguard Worker   if (!base::CommandLine::InitializedForCurrentProcess())
165*6777b538SAndroid Build Coastguard Worker     return nullptr;
166*6777b538SAndroid Build Coastguard Worker   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
167*6777b538SAndroid Build Coastguard Worker   if (!command_line->HasSwitch(switches::kV) &&
168*6777b538SAndroid Build Coastguard Worker       !command_line->HasSwitch(switches::kVModule)) {
169*6777b538SAndroid Build Coastguard Worker     return nullptr;
170*6777b538SAndroid Build Coastguard Worker   }
171*6777b538SAndroid Build Coastguard Worker #if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL)
172*6777b538SAndroid Build Coastguard Worker   // See comments on |g_vlog_info|.
173*6777b538SAndroid Build Coastguard Worker   ScopedLeakSanitizerDisabler lsan_disabler;
174*6777b538SAndroid Build Coastguard Worker #endif  // defined(LEAK_SANITIZER)
175*6777b538SAndroid Build Coastguard Worker   return std::make_unique<VlogInfo>(
176*6777b538SAndroid Build Coastguard Worker       command_line->GetSwitchValueASCII(switches::kV),
177*6777b538SAndroid Build Coastguard Worker       command_line->GetSwitchValueASCII(switches::kVModule), &g_min_log_level);
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker // If the commandline is initialized for the current process this will
181*6777b538SAndroid Build Coastguard Worker // initialize g_vlog_info. If there are no VLOG switches, it will initialize it
182*6777b538SAndroid Build Coastguard Worker // to |nullptr|.
MaybeInitializeVlogInfo()183*6777b538SAndroid Build Coastguard Worker void MaybeInitializeVlogInfo() {
184*6777b538SAndroid Build Coastguard Worker   if (base::CommandLine::InitializedForCurrentProcess()) {
185*6777b538SAndroid Build Coastguard Worker     std::unique_ptr<VlogInfo> vlog_info = VlogInfoFromCommandLine();
186*6777b538SAndroid Build Coastguard Worker     if (vlog_info) {
187*6777b538SAndroid Build Coastguard Worker       // VlogInfoFromCommandLine is annotated with ScopedLeakSanitizerDisabler
188*6777b538SAndroid Build Coastguard Worker       // so it's allowed to leak. If the object was installed, we release it.
189*6777b538SAndroid Build Coastguard Worker       if (InitializeVlogInfo(vlog_info.get())) {
190*6777b538SAndroid Build Coastguard Worker         vlog_info.release();
191*6777b538SAndroid Build Coastguard Worker       }
192*6777b538SAndroid Build Coastguard Worker     }
193*6777b538SAndroid Build Coastguard Worker   }
194*6777b538SAndroid Build Coastguard Worker }
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker const char* const log_severity_names[] = {"INFO", "WARNING", "ERROR", "FATAL"};
197*6777b538SAndroid Build Coastguard Worker static_assert(LOGGING_NUM_SEVERITIES == std::size(log_severity_names),
198*6777b538SAndroid Build Coastguard Worker               "Incorrect number of log_severity_names");
199*6777b538SAndroid Build Coastguard Worker 
log_severity_name(int severity)200*6777b538SAndroid Build Coastguard Worker const char* log_severity_name(int severity) {
201*6777b538SAndroid Build Coastguard Worker   if (severity >= 0 && severity < LOGGING_NUM_SEVERITIES)
202*6777b538SAndroid Build Coastguard Worker     return log_severity_names[severity];
203*6777b538SAndroid Build Coastguard Worker   return "UNKNOWN";
204*6777b538SAndroid Build Coastguard Worker }
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker // Specifies the process' logging sink(s), represented as a combination of
207*6777b538SAndroid Build Coastguard Worker // LoggingDestination values joined by bitwise OR.
208*6777b538SAndroid Build Coastguard Worker uint32_t g_logging_destination = LOG_DEFAULT;
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
211*6777b538SAndroid Build Coastguard Worker // Specifies the format of log header for chrome os.
212*6777b538SAndroid Build Coastguard Worker LogFormat g_log_format = LogFormat::LOG_FORMAT_SYSLOG;
213*6777b538SAndroid Build Coastguard Worker #endif
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
216*6777b538SAndroid Build Coastguard Worker // Retains system logging structures.
GetScopedFxLogger()217*6777b538SAndroid Build Coastguard Worker base::ScopedFxLogger& GetScopedFxLogger() {
218*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<base::ScopedFxLogger> logger;
219*6777b538SAndroid Build Coastguard Worker   return *logger;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker #endif
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker // For LOGGING_ERROR and above, always print to stderr.
224*6777b538SAndroid Build Coastguard Worker const int kAlwaysPrintErrorLevel = LOGGING_ERROR;
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker // Which log file to use? This is initialized by InitLogging or
227*6777b538SAndroid Build Coastguard Worker // will be lazily initialized to the default value when it is
228*6777b538SAndroid Build Coastguard Worker // first needed.
229*6777b538SAndroid Build Coastguard Worker using PathString = base::FilePath::StringType;
230*6777b538SAndroid Build Coastguard Worker PathString* g_log_file_name = nullptr;
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker // This file is lazily opened and the handle may be nullptr
233*6777b538SAndroid Build Coastguard Worker FileHandle g_log_file = nullptr;
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker // What should be prepended to each message?
236*6777b538SAndroid Build Coastguard Worker bool g_log_process_id = false;
237*6777b538SAndroid Build Coastguard Worker bool g_log_thread_id = false;
238*6777b538SAndroid Build Coastguard Worker bool g_log_timestamp = true;
239*6777b538SAndroid Build Coastguard Worker bool g_log_tickcount = false;
240*6777b538SAndroid Build Coastguard Worker const char* g_log_prefix = nullptr;
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker // Should we pop up fatal debug messages in a dialog?
243*6777b538SAndroid Build Coastguard Worker bool show_error_dialogs = false;
244*6777b538SAndroid Build Coastguard Worker 
245*6777b538SAndroid Build Coastguard Worker // An assert handler override specified by the client to be called instead of
246*6777b538SAndroid Build Coastguard Worker // the debug message dialog and process termination. Assert handlers are stored
247*6777b538SAndroid Build Coastguard Worker // in stack to allow overriding and restoring.
GetLogAssertHandlerStack()248*6777b538SAndroid Build Coastguard Worker base::stack<LogAssertHandlerFunction>& GetLogAssertHandlerStack() {
249*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<base::stack<LogAssertHandlerFunction>> instance;
250*6777b538SAndroid Build Coastguard Worker   return *instance;
251*6777b538SAndroid Build Coastguard Worker }
252*6777b538SAndroid Build Coastguard Worker 
253*6777b538SAndroid Build Coastguard Worker // A log message handler that gets notified of every log message we process.
254*6777b538SAndroid Build Coastguard Worker LogMessageHandlerFunction g_log_message_handler = nullptr;
255*6777b538SAndroid Build Coastguard Worker 
TickCount()256*6777b538SAndroid Build Coastguard Worker uint64_t TickCount() {
257*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
258*6777b538SAndroid Build Coastguard Worker   return GetTickCount();
259*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_FUCHSIA)
260*6777b538SAndroid Build Coastguard Worker   return static_cast<uint64_t>(
261*6777b538SAndroid Build Coastguard Worker       zx_clock_get_monotonic() /
262*6777b538SAndroid Build Coastguard Worker       static_cast<zx_time_t>(base::Time::kNanosecondsPerMicrosecond));
263*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_APPLE)
264*6777b538SAndroid Build Coastguard Worker   return mach_absolute_time();
265*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_NACL)
266*6777b538SAndroid Build Coastguard Worker   // NaCl sadly does not have _POSIX_TIMERS enabled in sys/features.h
267*6777b538SAndroid Build Coastguard Worker   // So we have to use clock() for now.
268*6777b538SAndroid Build Coastguard Worker   return clock();
269*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX)
270*6777b538SAndroid Build Coastguard Worker   struct timespec ts;
271*6777b538SAndroid Build Coastguard Worker   clock_gettime(CLOCK_MONOTONIC, &ts);
272*6777b538SAndroid Build Coastguard Worker 
273*6777b538SAndroid Build Coastguard Worker   uint64_t absolute_micro = static_cast<uint64_t>(ts.tv_sec) * 1000000 +
274*6777b538SAndroid Build Coastguard Worker                             static_cast<uint64_t>(ts.tv_nsec) / 1000;
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker   return absolute_micro;
277*6777b538SAndroid Build Coastguard Worker #endif
278*6777b538SAndroid Build Coastguard Worker }
279*6777b538SAndroid Build Coastguard Worker 
DeleteFilePath(const PathString & log_name)280*6777b538SAndroid Build Coastguard Worker void DeleteFilePath(const PathString& log_name) {
281*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
282*6777b538SAndroid Build Coastguard Worker   DeleteFile(log_name.c_str());
283*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_NACL)
284*6777b538SAndroid Build Coastguard Worker   // Do nothing; unlink() isn't supported on NaCl.
285*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
286*6777b538SAndroid Build Coastguard Worker   unlink(log_name.c_str());
287*6777b538SAndroid Build Coastguard Worker #else
288*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
289*6777b538SAndroid Build Coastguard Worker #endif
290*6777b538SAndroid Build Coastguard Worker }
291*6777b538SAndroid Build Coastguard Worker 
GetDefaultLogFile()292*6777b538SAndroid Build Coastguard Worker PathString GetDefaultLogFile() {
293*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
294*6777b538SAndroid Build Coastguard Worker   // On Windows we use the same path as the exe.
295*6777b538SAndroid Build Coastguard Worker   wchar_t module_name[MAX_PATH];
296*6777b538SAndroid Build Coastguard Worker   GetModuleFileName(nullptr, module_name, MAX_PATH);
297*6777b538SAndroid Build Coastguard Worker 
298*6777b538SAndroid Build Coastguard Worker   PathString log_name = module_name;
299*6777b538SAndroid Build Coastguard Worker   PathString::size_type last_backslash = log_name.rfind('\\', log_name.size());
300*6777b538SAndroid Build Coastguard Worker   if (last_backslash != PathString::npos)
301*6777b538SAndroid Build Coastguard Worker     log_name.erase(last_backslash + 1);
302*6777b538SAndroid Build Coastguard Worker   log_name += FILE_PATH_LITERAL("debug.log");
303*6777b538SAndroid Build Coastguard Worker   return log_name;
304*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
305*6777b538SAndroid Build Coastguard Worker   // On other platforms we just use the current directory.
306*6777b538SAndroid Build Coastguard Worker   return PathString("debug.log");
307*6777b538SAndroid Build Coastguard Worker #endif
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker // We don't need locks on Windows for atomically appending to files. The OS
311*6777b538SAndroid Build Coastguard Worker // provides this functionality.
312*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
313*6777b538SAndroid Build Coastguard Worker 
314*6777b538SAndroid Build Coastguard Worker // Provides a lock to synchronize appending to the log file across
315*6777b538SAndroid Build Coastguard Worker // threads. This can be required to support NFS file systems even on OSes that
316*6777b538SAndroid Build Coastguard Worker // provide atomic append operations in most cases. It should be noted that this
317*6777b538SAndroid Build Coastguard Worker // lock is not not shared across processes. When using NFS filesystems
318*6777b538SAndroid Build Coastguard Worker // protection against clobbering between different processes will be best-effort
319*6777b538SAndroid Build Coastguard Worker // and provided by the OS. See
320*6777b538SAndroid Build Coastguard Worker // https://man7.org/linux/man-pages/man2/open.2.html.
321*6777b538SAndroid Build Coastguard Worker //
322*6777b538SAndroid Build Coastguard Worker // The lock also protects initializing and closing the log file which can
323*6777b538SAndroid Build Coastguard Worker // happen concurrently with logging on some platforms like ChromeOS that need to
324*6777b538SAndroid Build Coastguard Worker // redirect logging by calling BaseInitLoggingImpl() twice.
GetLoggingLock()325*6777b538SAndroid Build Coastguard Worker base::Lock& GetLoggingLock() {
326*6777b538SAndroid Build Coastguard Worker   static base::NoDestructor<base::Lock> lock;
327*6777b538SAndroid Build Coastguard Worker   return *lock;
328*6777b538SAndroid Build Coastguard Worker }
329*6777b538SAndroid Build Coastguard Worker 
330*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
331*6777b538SAndroid Build Coastguard Worker 
332*6777b538SAndroid Build Coastguard Worker // Called by logging functions to ensure that |g_log_file| is initialized
333*6777b538SAndroid Build Coastguard Worker // and can be used for writing. Returns false if the file could not be
334*6777b538SAndroid Build Coastguard Worker // initialized. |g_log_file| will be nullptr in this case.
InitializeLogFileHandle()335*6777b538SAndroid Build Coastguard Worker bool InitializeLogFileHandle() {
336*6777b538SAndroid Build Coastguard Worker   if (g_log_file)
337*6777b538SAndroid Build Coastguard Worker     return true;
338*6777b538SAndroid Build Coastguard Worker 
339*6777b538SAndroid Build Coastguard Worker   if (!g_log_file_name) {
340*6777b538SAndroid Build Coastguard Worker     // Nobody has called InitLogging to specify a debug log file, so here we
341*6777b538SAndroid Build Coastguard Worker     // initialize the log file name to a default.
342*6777b538SAndroid Build Coastguard Worker     g_log_file_name = new PathString(GetDefaultLogFile());
343*6777b538SAndroid Build Coastguard Worker   }
344*6777b538SAndroid Build Coastguard Worker 
345*6777b538SAndroid Build Coastguard Worker   if ((g_logging_destination & LOG_TO_FILE) == 0)
346*6777b538SAndroid Build Coastguard Worker     return true;
347*6777b538SAndroid Build Coastguard Worker 
348*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
349*6777b538SAndroid Build Coastguard Worker   // The FILE_APPEND_DATA access mask ensures that the file is atomically
350*6777b538SAndroid Build Coastguard Worker   // appended to across accesses from multiple threads.
351*6777b538SAndroid Build Coastguard Worker   // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364399(v=vs.85).aspx
352*6777b538SAndroid Build Coastguard Worker   // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
353*6777b538SAndroid Build Coastguard Worker   g_log_file = CreateFile(g_log_file_name->c_str(), FILE_APPEND_DATA,
354*6777b538SAndroid Build Coastguard Worker                           FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
355*6777b538SAndroid Build Coastguard Worker                           OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
356*6777b538SAndroid Build Coastguard Worker   if (g_log_file == INVALID_HANDLE_VALUE || g_log_file == nullptr) {
357*6777b538SAndroid Build Coastguard Worker     // We are intentionally not using FilePath or FileUtil here to reduce the
358*6777b538SAndroid Build Coastguard Worker     // dependencies of the logging implementation. For e.g. FilePath and
359*6777b538SAndroid Build Coastguard Worker     // FileUtil depend on shell32 and user32.dll. This is not acceptable for
360*6777b538SAndroid Build Coastguard Worker     // some consumers of base logging like chrome_elf, etc.
361*6777b538SAndroid Build Coastguard Worker     // Please don't change the code below to use FilePath.
362*6777b538SAndroid Build Coastguard Worker     // try the current directory
363*6777b538SAndroid Build Coastguard Worker     wchar_t system_buffer[MAX_PATH];
364*6777b538SAndroid Build Coastguard Worker     system_buffer[0] = 0;
365*6777b538SAndroid Build Coastguard Worker     DWORD len = ::GetCurrentDirectory(std::size(system_buffer), system_buffer);
366*6777b538SAndroid Build Coastguard Worker     if (len == 0 || len > std::size(system_buffer))
367*6777b538SAndroid Build Coastguard Worker       return false;
368*6777b538SAndroid Build Coastguard Worker 
369*6777b538SAndroid Build Coastguard Worker     *g_log_file_name = system_buffer;
370*6777b538SAndroid Build Coastguard Worker     // Append a trailing backslash if needed.
371*6777b538SAndroid Build Coastguard Worker     if (g_log_file_name->back() != L'\\')
372*6777b538SAndroid Build Coastguard Worker       *g_log_file_name += FILE_PATH_LITERAL("\\");
373*6777b538SAndroid Build Coastguard Worker     *g_log_file_name += FILE_PATH_LITERAL("debug.log");
374*6777b538SAndroid Build Coastguard Worker 
375*6777b538SAndroid Build Coastguard Worker     g_log_file = CreateFile(g_log_file_name->c_str(), FILE_APPEND_DATA,
376*6777b538SAndroid Build Coastguard Worker                             FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
377*6777b538SAndroid Build Coastguard Worker                             OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
378*6777b538SAndroid Build Coastguard Worker     if (g_log_file == INVALID_HANDLE_VALUE || g_log_file == nullptr) {
379*6777b538SAndroid Build Coastguard Worker       g_log_file = nullptr;
380*6777b538SAndroid Build Coastguard Worker       return false;
381*6777b538SAndroid Build Coastguard Worker     }
382*6777b538SAndroid Build Coastguard Worker   }
383*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
384*6777b538SAndroid Build Coastguard Worker   g_log_file = fopen(g_log_file_name->c_str(), "a");
385*6777b538SAndroid Build Coastguard Worker   if (g_log_file == nullptr)
386*6777b538SAndroid Build Coastguard Worker     return false;
387*6777b538SAndroid Build Coastguard Worker #else
388*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
389*6777b538SAndroid Build Coastguard Worker #endif
390*6777b538SAndroid Build Coastguard Worker 
391*6777b538SAndroid Build Coastguard Worker   return true;
392*6777b538SAndroid Build Coastguard Worker }
393*6777b538SAndroid Build Coastguard Worker 
CloseFile(FileHandle log)394*6777b538SAndroid Build Coastguard Worker void CloseFile(FileHandle log) {
395*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
396*6777b538SAndroid Build Coastguard Worker   CloseHandle(log);
397*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
398*6777b538SAndroid Build Coastguard Worker   fclose(log);
399*6777b538SAndroid Build Coastguard Worker #else
400*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
401*6777b538SAndroid Build Coastguard Worker #endif
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker 
CloseLogFileUnlocked()404*6777b538SAndroid Build Coastguard Worker void CloseLogFileUnlocked() {
405*6777b538SAndroid Build Coastguard Worker   if (!g_log_file)
406*6777b538SAndroid Build Coastguard Worker     return;
407*6777b538SAndroid Build Coastguard Worker 
408*6777b538SAndroid Build Coastguard Worker   CloseFile(g_log_file);
409*6777b538SAndroid Build Coastguard Worker   g_log_file = nullptr;
410*6777b538SAndroid Build Coastguard Worker 
411*6777b538SAndroid Build Coastguard Worker   // If we initialized logging via an externally-provided file descriptor, we
412*6777b538SAndroid Build Coastguard Worker   // won't have a log path set and shouldn't try to reopen the log file.
413*6777b538SAndroid Build Coastguard Worker   if (!g_log_file_name)
414*6777b538SAndroid Build Coastguard Worker     g_logging_destination &= ~LOG_TO_FILE;
415*6777b538SAndroid Build Coastguard Worker }
416*6777b538SAndroid Build Coastguard Worker 
417*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
LogSeverityToFuchsiaLogSeverity(LogSeverity severity)418*6777b538SAndroid Build Coastguard Worker inline FuchsiaLogSeverity LogSeverityToFuchsiaLogSeverity(
419*6777b538SAndroid Build Coastguard Worker     LogSeverity severity) {
420*6777b538SAndroid Build Coastguard Worker   switch (severity) {
421*6777b538SAndroid Build Coastguard Worker     case LOGGING_INFO:
422*6777b538SAndroid Build Coastguard Worker       return FUCHSIA_LOG_INFO;
423*6777b538SAndroid Build Coastguard Worker     case LOGGING_WARNING:
424*6777b538SAndroid Build Coastguard Worker       return FUCHSIA_LOG_WARNING;
425*6777b538SAndroid Build Coastguard Worker     case LOGGING_ERROR:
426*6777b538SAndroid Build Coastguard Worker       return FUCHSIA_LOG_ERROR;
427*6777b538SAndroid Build Coastguard Worker     case LOGGING_FATAL:
428*6777b538SAndroid Build Coastguard Worker       // Don't use FX_LOG_FATAL, otherwise fx_logger_log() will abort().
429*6777b538SAndroid Build Coastguard Worker       return FUCHSIA_LOG_ERROR;
430*6777b538SAndroid Build Coastguard Worker   }
431*6777b538SAndroid Build Coastguard Worker   if (severity > -3) {
432*6777b538SAndroid Build Coastguard Worker     // LOGGING_VERBOSE levels 1 and 2.
433*6777b538SAndroid Build Coastguard Worker     return FUCHSIA_LOG_DEBUG;
434*6777b538SAndroid Build Coastguard Worker   }
435*6777b538SAndroid Build Coastguard Worker   // LOGGING_VERBOSE levels 3 and higher, or incorrect levels.
436*6777b538SAndroid Build Coastguard Worker   return FUCHSIA_LOG_TRACE;
437*6777b538SAndroid Build Coastguard Worker }
438*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_FUCHSIA)
439*6777b538SAndroid Build Coastguard Worker 
WriteToFd(int fd,const char * data,size_t length)440*6777b538SAndroid Build Coastguard Worker void WriteToFd(int fd, const char* data, size_t length) {
441*6777b538SAndroid Build Coastguard Worker   size_t bytes_written = 0;
442*6777b538SAndroid Build Coastguard Worker   long rv;
443*6777b538SAndroid Build Coastguard Worker   while (bytes_written < length) {
444*6777b538SAndroid Build Coastguard Worker     rv = HANDLE_EINTR(write(fd, data + bytes_written, length - bytes_written));
445*6777b538SAndroid Build Coastguard Worker     if (rv < 0) {
446*6777b538SAndroid Build Coastguard Worker       // Give up, nothing we can do now.
447*6777b538SAndroid Build Coastguard Worker       break;
448*6777b538SAndroid Build Coastguard Worker     }
449*6777b538SAndroid Build Coastguard Worker     bytes_written += static_cast<size_t>(rv);
450*6777b538SAndroid Build Coastguard Worker   }
451*6777b538SAndroid Build Coastguard Worker }
452*6777b538SAndroid Build Coastguard Worker 
SetLogFatalCrashKey(LogMessage * log_message)453*6777b538SAndroid Build Coastguard Worker void SetLogFatalCrashKey(LogMessage* log_message) {
454*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
455*6777b538SAndroid Build Coastguard Worker   // In case of an out-of-memory condition, this code could be reentered when
456*6777b538SAndroid Build Coastguard Worker   // constructing and storing the key. Using a static is not thread-safe, but if
457*6777b538SAndroid Build Coastguard Worker   // multiple threads are in the process of a fatal crash at the same time, this
458*6777b538SAndroid Build Coastguard Worker   // should work.
459*6777b538SAndroid Build Coastguard Worker   static bool guarded = false;
460*6777b538SAndroid Build Coastguard Worker   if (guarded)
461*6777b538SAndroid Build Coastguard Worker     return;
462*6777b538SAndroid Build Coastguard Worker 
463*6777b538SAndroid Build Coastguard Worker   base::AutoReset<bool> guard(&guarded, true);
464*6777b538SAndroid Build Coastguard Worker 
465*6777b538SAndroid Build Coastguard Worker   // Note that we intentionally use LOG_FATAL here (old name for LOGGING_FATAL)
466*6777b538SAndroid Build Coastguard Worker   // as that's understood and used by the crash backend.
467*6777b538SAndroid Build Coastguard Worker   static auto* const crash_key = base::debug::AllocateCrashKeyString(
468*6777b538SAndroid Build Coastguard Worker       "LOG_FATAL", base::debug::CrashKeySize::Size1024);
469*6777b538SAndroid Build Coastguard Worker   base::debug::SetCrashKeyString(crash_key, log_message->BuildCrashString());
470*6777b538SAndroid Build Coastguard Worker 
471*6777b538SAndroid Build Coastguard Worker #endif  // !BUILDFLAG(IS_NACL)
472*6777b538SAndroid Build Coastguard Worker }
473*6777b538SAndroid Build Coastguard Worker 
BuildCrashString(const char * file,int line,const char * message_without_prefix)474*6777b538SAndroid Build Coastguard Worker std::string BuildCrashString(const char* file,
475*6777b538SAndroid Build Coastguard Worker                              int line,
476*6777b538SAndroid Build Coastguard Worker                              const char* message_without_prefix) {
477*6777b538SAndroid Build Coastguard Worker   // Only log last path component.
478*6777b538SAndroid Build Coastguard Worker   if (file) {
479*6777b538SAndroid Build Coastguard Worker     const char* slash = strrchr(file,
480*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
481*6777b538SAndroid Build Coastguard Worker                                 '\\'
482*6777b538SAndroid Build Coastguard Worker #else
483*6777b538SAndroid Build Coastguard Worker                                 '/'
484*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
485*6777b538SAndroid Build Coastguard Worker     );
486*6777b538SAndroid Build Coastguard Worker     if (slash) {
487*6777b538SAndroid Build Coastguard Worker       file = slash + 1;
488*6777b538SAndroid Build Coastguard Worker     }
489*6777b538SAndroid Build Coastguard Worker   }
490*6777b538SAndroid Build Coastguard Worker 
491*6777b538SAndroid Build Coastguard Worker   return base::StringPrintf("%s:%d: %s", file, line, message_without_prefix);
492*6777b538SAndroid Build Coastguard Worker }
493*6777b538SAndroid Build Coastguard Worker 
494*6777b538SAndroid Build Coastguard Worker // Invokes macro to record trace event when a log message is emitted.
TraceLogMessage(const char * file,int line,const std::string & message)495*6777b538SAndroid Build Coastguard Worker void TraceLogMessage(const char* file, int line, const std::string& message) {
496*6777b538SAndroid Build Coastguard Worker   TRACE_EVENT_INSTANT("log", "LogMessage", [&](perfetto::EventContext ctx) {
497*6777b538SAndroid Build Coastguard Worker     perfetto::protos::pbzero::LogMessage* log = ctx.event()->set_log_message();
498*6777b538SAndroid Build Coastguard Worker     log->set_source_location_iid(base::trace_event::InternedSourceLocation::Get(
499*6777b538SAndroid Build Coastguard Worker         &ctx, base::trace_event::TraceSourceLocation(/*function_name=*/nullptr,
500*6777b538SAndroid Build Coastguard Worker                                                      file, line)));
501*6777b538SAndroid Build Coastguard Worker     log->set_body_iid(
502*6777b538SAndroid Build Coastguard Worker         base::trace_event::InternedLogMessage::Get(&ctx, message));
503*6777b538SAndroid Build Coastguard Worker   });
504*6777b538SAndroid Build Coastguard Worker }
505*6777b538SAndroid Build Coastguard Worker 
506*6777b538SAndroid Build Coastguard Worker }  // namespace
507*6777b538SAndroid Build Coastguard Worker 
508*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
509*6777b538SAndroid Build Coastguard Worker // In DCHECK-enabled Chrome builds, allow the meaning of LOGGING_DCHECK to be
510*6777b538SAndroid Build Coastguard Worker // determined at run-time. We default it to ERROR, to avoid it triggering
511*6777b538SAndroid Build Coastguard Worker // crashes before the run-time has explicitly chosen the behaviour.
512*6777b538SAndroid Build Coastguard Worker BASE_EXPORT logging::LogSeverity LOGGING_DCHECK = LOGGING_ERROR;
513*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(DCHECK_IS_CONFIGURABLE)
514*6777b538SAndroid Build Coastguard Worker 
515*6777b538SAndroid Build Coastguard Worker // This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to have
516*6777b538SAndroid Build Coastguard Worker // an object of the correct type on the LHS of the unused part of the ternary
517*6777b538SAndroid Build Coastguard Worker // operator.
518*6777b538SAndroid Build Coastguard Worker std::ostream* g_swallow_stream;
519*6777b538SAndroid Build Coastguard Worker 
BaseInitLoggingImpl(const LoggingSettings & settings)520*6777b538SAndroid Build Coastguard Worker bool BaseInitLoggingImpl(const LoggingSettings& settings) {
521*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_NACL)
522*6777b538SAndroid Build Coastguard Worker   // Can log only to the system debug log and stderr.
523*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(settings.logging_dest & ~(LOG_TO_SYSTEM_DEBUG_LOG | LOG_TO_STDERR),
524*6777b538SAndroid Build Coastguard Worker            0u);
525*6777b538SAndroid Build Coastguard Worker #endif
526*6777b538SAndroid Build Coastguard Worker 
527*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
528*6777b538SAndroid Build Coastguard Worker   g_log_format = settings.log_format;
529*6777b538SAndroid Build Coastguard Worker #endif
530*6777b538SAndroid Build Coastguard Worker 
531*6777b538SAndroid Build Coastguard Worker   MaybeInitializeVlogInfo();
532*6777b538SAndroid Build Coastguard Worker 
533*6777b538SAndroid Build Coastguard Worker   g_logging_destination = settings.logging_dest;
534*6777b538SAndroid Build Coastguard Worker 
535*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
536*6777b538SAndroid Build Coastguard Worker   if (g_logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) {
537*6777b538SAndroid Build Coastguard Worker     GetScopedFxLogger() = base::ScopedFxLogger::CreateForProcess();
538*6777b538SAndroid Build Coastguard Worker   }
539*6777b538SAndroid Build Coastguard Worker #endif
540*6777b538SAndroid Build Coastguard Worker 
541*6777b538SAndroid Build Coastguard Worker   // Ignore file options unless logging to file is set.
542*6777b538SAndroid Build Coastguard Worker   if ((g_logging_destination & LOG_TO_FILE) == 0)
543*6777b538SAndroid Build Coastguard Worker     return true;
544*6777b538SAndroid Build Coastguard Worker 
545*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
546*6777b538SAndroid Build Coastguard Worker   base::AutoLock guard(GetLoggingLock());
547*6777b538SAndroid Build Coastguard Worker #endif
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker   // Calling InitLogging twice or after some log call has already opened the
550*6777b538SAndroid Build Coastguard Worker   // default log file will re-initialize to the new options.
551*6777b538SAndroid Build Coastguard Worker   CloseLogFileUnlocked();
552*6777b538SAndroid Build Coastguard Worker 
553*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
554*6777b538SAndroid Build Coastguard Worker   if (settings.log_file) {
555*6777b538SAndroid Build Coastguard Worker     CHECK(settings.log_file_path.empty(), base::NotFatalUntil::M127);
556*6777b538SAndroid Build Coastguard Worker     g_log_file = settings.log_file;
557*6777b538SAndroid Build Coastguard Worker     return true;
558*6777b538SAndroid Build Coastguard Worker   }
559*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
560*6777b538SAndroid Build Coastguard Worker 
561*6777b538SAndroid Build Coastguard Worker   CHECK(!settings.log_file_path.empty(), base::NotFatalUntil::M127)
562*6777b538SAndroid Build Coastguard Worker       << "LOG_TO_FILE set but no log_file_path!";
563*6777b538SAndroid Build Coastguard Worker 
564*6777b538SAndroid Build Coastguard Worker   if (!g_log_file_name)
565*6777b538SAndroid Build Coastguard Worker     g_log_file_name = new PathString();
566*6777b538SAndroid Build Coastguard Worker   *g_log_file_name = settings.log_file_path;
567*6777b538SAndroid Build Coastguard Worker   if (settings.delete_old == DELETE_OLD_LOG_FILE)
568*6777b538SAndroid Build Coastguard Worker     DeleteFilePath(*g_log_file_name);
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker   return InitializeLogFileHandle();
571*6777b538SAndroid Build Coastguard Worker }
572*6777b538SAndroid Build Coastguard Worker 
SetMinLogLevel(int level)573*6777b538SAndroid Build Coastguard Worker void SetMinLogLevel(int level) {
574*6777b538SAndroid Build Coastguard Worker   g_min_log_level = std::min(LOGGING_FATAL, level);
575*6777b538SAndroid Build Coastguard Worker }
576*6777b538SAndroid Build Coastguard Worker 
GetMinLogLevel()577*6777b538SAndroid Build Coastguard Worker int GetMinLogLevel() {
578*6777b538SAndroid Build Coastguard Worker   return g_min_log_level;
579*6777b538SAndroid Build Coastguard Worker }
580*6777b538SAndroid Build Coastguard Worker 
ShouldCreateLogMessage(int severity)581*6777b538SAndroid Build Coastguard Worker bool ShouldCreateLogMessage(int severity) {
582*6777b538SAndroid Build Coastguard Worker   if (severity < g_min_log_level)
583*6777b538SAndroid Build Coastguard Worker     return false;
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker   // Return true here unless we know ~LogMessage won't do anything.
586*6777b538SAndroid Build Coastguard Worker   return g_logging_destination != LOG_NONE || g_log_message_handler ||
587*6777b538SAndroid Build Coastguard Worker          severity >= kAlwaysPrintErrorLevel;
588*6777b538SAndroid Build Coastguard Worker }
589*6777b538SAndroid Build Coastguard Worker 
590*6777b538SAndroid Build Coastguard Worker // Returns true when LOG_TO_STDERR flag is set, or |severity| is high.
591*6777b538SAndroid Build Coastguard Worker // If |severity| is high then true will be returned when no log destinations are
592*6777b538SAndroid Build Coastguard Worker // set, or only LOG_TO_FILE is set, since that is useful for local development
593*6777b538SAndroid Build Coastguard Worker // and debugging.
ShouldLogToStderr(int severity)594*6777b538SAndroid Build Coastguard Worker bool ShouldLogToStderr(int severity) {
595*6777b538SAndroid Build Coastguard Worker   if (g_logging_destination & LOG_TO_STDERR)
596*6777b538SAndroid Build Coastguard Worker     return true;
597*6777b538SAndroid Build Coastguard Worker 
598*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
599*6777b538SAndroid Build Coastguard Worker   // Fuchsia will persist data logged to stdio by a component, so do not emit
600*6777b538SAndroid Build Coastguard Worker   // logs to stderr unless explicitly configured to do so.
601*6777b538SAndroid Build Coastguard Worker   return false;
602*6777b538SAndroid Build Coastguard Worker #else
603*6777b538SAndroid Build Coastguard Worker   if (severity >= kAlwaysPrintErrorLevel)
604*6777b538SAndroid Build Coastguard Worker     return (g_logging_destination & ~LOG_TO_FILE) == LOG_NONE;
605*6777b538SAndroid Build Coastguard Worker   return false;
606*6777b538SAndroid Build Coastguard Worker #endif
607*6777b538SAndroid Build Coastguard Worker }
608*6777b538SAndroid Build Coastguard Worker 
GetVlogVerbosity()609*6777b538SAndroid Build Coastguard Worker int GetVlogVerbosity() {
610*6777b538SAndroid Build Coastguard Worker   return std::max(-1, LOGGING_INFO - GetMinLogLevel());
611*6777b538SAndroid Build Coastguard Worker }
612*6777b538SAndroid Build Coastguard Worker 
GetVlogLevelHelper(const char * file,size_t N)613*6777b538SAndroid Build Coastguard Worker int GetVlogLevelHelper(const char* file, size_t N) {
614*6777b538SAndroid Build Coastguard Worker   DCHECK_GT(N, 0U);
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker   // Note: |g_vlog_info| may change on a different thread during startup
617*6777b538SAndroid Build Coastguard Worker   // (but will always be valid or nullptr).
618*6777b538SAndroid Build Coastguard Worker   VlogInfo* vlog_info = GetVlogInfo();
619*6777b538SAndroid Build Coastguard Worker   return vlog_info ?
620*6777b538SAndroid Build Coastguard Worker       vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) :
621*6777b538SAndroid Build Coastguard Worker       GetVlogVerbosity();
622*6777b538SAndroid Build Coastguard Worker }
623*6777b538SAndroid Build Coastguard Worker 
SetLogItems(bool enable_process_id,bool enable_thread_id,bool enable_timestamp,bool enable_tickcount)624*6777b538SAndroid Build Coastguard Worker void SetLogItems(bool enable_process_id, bool enable_thread_id,
625*6777b538SAndroid Build Coastguard Worker                  bool enable_timestamp, bool enable_tickcount) {
626*6777b538SAndroid Build Coastguard Worker   g_log_process_id = enable_process_id;
627*6777b538SAndroid Build Coastguard Worker   g_log_thread_id = enable_thread_id;
628*6777b538SAndroid Build Coastguard Worker   g_log_timestamp = enable_timestamp;
629*6777b538SAndroid Build Coastguard Worker   g_log_tickcount = enable_tickcount;
630*6777b538SAndroid Build Coastguard Worker }
631*6777b538SAndroid Build Coastguard Worker 
SetLogPrefix(const char * prefix)632*6777b538SAndroid Build Coastguard Worker void SetLogPrefix(const char* prefix) {
633*6777b538SAndroid Build Coastguard Worker   DCHECK(!prefix ||
634*6777b538SAndroid Build Coastguard Worker          base::ContainsOnlyChars(prefix, "abcdefghijklmnopqrstuvwxyz"));
635*6777b538SAndroid Build Coastguard Worker   g_log_prefix = prefix;
636*6777b538SAndroid Build Coastguard Worker }
637*6777b538SAndroid Build Coastguard Worker 
SetShowErrorDialogs(bool enable_dialogs)638*6777b538SAndroid Build Coastguard Worker void SetShowErrorDialogs(bool enable_dialogs) {
639*6777b538SAndroid Build Coastguard Worker   show_error_dialogs = enable_dialogs;
640*6777b538SAndroid Build Coastguard Worker }
641*6777b538SAndroid Build Coastguard Worker 
ScopedLogAssertHandler(LogAssertHandlerFunction handler)642*6777b538SAndroid Build Coastguard Worker ScopedLogAssertHandler::ScopedLogAssertHandler(
643*6777b538SAndroid Build Coastguard Worker     LogAssertHandlerFunction handler) {
644*6777b538SAndroid Build Coastguard Worker   GetLogAssertHandlerStack().push(std::move(handler));
645*6777b538SAndroid Build Coastguard Worker }
646*6777b538SAndroid Build Coastguard Worker 
~ScopedLogAssertHandler()647*6777b538SAndroid Build Coastguard Worker ScopedLogAssertHandler::~ScopedLogAssertHandler() {
648*6777b538SAndroid Build Coastguard Worker   GetLogAssertHandlerStack().pop();
649*6777b538SAndroid Build Coastguard Worker }
650*6777b538SAndroid Build Coastguard Worker 
SetLogMessageHandler(LogMessageHandlerFunction handler)651*6777b538SAndroid Build Coastguard Worker void SetLogMessageHandler(LogMessageHandlerFunction handler) {
652*6777b538SAndroid Build Coastguard Worker   g_log_message_handler = handler;
653*6777b538SAndroid Build Coastguard Worker }
654*6777b538SAndroid Build Coastguard Worker 
GetLogMessageHandler()655*6777b538SAndroid Build Coastguard Worker LogMessageHandlerFunction GetLogMessageHandler() {
656*6777b538SAndroid Build Coastguard Worker   return g_log_message_handler;
657*6777b538SAndroid Build Coastguard Worker }
658*6777b538SAndroid Build Coastguard Worker 
659*6777b538SAndroid Build Coastguard Worker #if !defined(NDEBUG)
660*6777b538SAndroid Build Coastguard Worker // Displays a message box to the user with the error message in it.
661*6777b538SAndroid Build Coastguard Worker // Used for fatal messages, where we close the app simultaneously.
662*6777b538SAndroid Build Coastguard Worker // This is for developers only; we don't use this in circumstances
663*6777b538SAndroid Build Coastguard Worker // (like release builds) where users could see it, since users don't
664*6777b538SAndroid Build Coastguard Worker // understand these messages anyway.
DisplayDebugMessageInDialog(const std::string & str)665*6777b538SAndroid Build Coastguard Worker void DisplayDebugMessageInDialog(const std::string& str) {
666*6777b538SAndroid Build Coastguard Worker   if (str.empty())
667*6777b538SAndroid Build Coastguard Worker     return;
668*6777b538SAndroid Build Coastguard Worker 
669*6777b538SAndroid Build Coastguard Worker   if (!show_error_dialogs)
670*6777b538SAndroid Build Coastguard Worker     return;
671*6777b538SAndroid Build Coastguard Worker 
672*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
673*6777b538SAndroid Build Coastguard Worker   // We intentionally don't implement a dialog on other platforms.
674*6777b538SAndroid Build Coastguard Worker   // You can just look at stderr.
675*6777b538SAndroid Build Coastguard Worker   if (base::win::IsUser32AndGdi32Available()) {
676*6777b538SAndroid Build Coastguard Worker     MessageBoxW(nullptr, base::as_wcstr(base::UTF8ToUTF16(str)), L"Fatal error",
677*6777b538SAndroid Build Coastguard Worker                 MB_OK | MB_ICONHAND | MB_TOPMOST);
678*6777b538SAndroid Build Coastguard Worker   } else {
679*6777b538SAndroid Build Coastguard Worker     OutputDebugStringW(base::as_wcstr(base::UTF8ToUTF16(str)));
680*6777b538SAndroid Build Coastguard Worker   }
681*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
682*6777b538SAndroid Build Coastguard Worker }
683*6777b538SAndroid Build Coastguard Worker #endif  // !defined(NDEBUG)
684*6777b538SAndroid Build Coastguard Worker 
LogMessage(const char * file,int line,LogSeverity severity)685*6777b538SAndroid Build Coastguard Worker LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
686*6777b538SAndroid Build Coastguard Worker     : severity_(severity), file_(file), line_(line) {
687*6777b538SAndroid Build Coastguard Worker   Init(file, line);
688*6777b538SAndroid Build Coastguard Worker }
689*6777b538SAndroid Build Coastguard Worker 
LogMessage(const char * file,int line,const char * condition)690*6777b538SAndroid Build Coastguard Worker LogMessage::LogMessage(const char* file, int line, const char* condition)
691*6777b538SAndroid Build Coastguard Worker     : severity_(LOGGING_FATAL), file_(file), line_(line) {
692*6777b538SAndroid Build Coastguard Worker   Init(file, line);
693*6777b538SAndroid Build Coastguard Worker   stream_ << "Check failed: " << condition << ". ";
694*6777b538SAndroid Build Coastguard Worker }
695*6777b538SAndroid Build Coastguard Worker 
~LogMessage()696*6777b538SAndroid Build Coastguard Worker LogMessage::~LogMessage() {
697*6777b538SAndroid Build Coastguard Worker   Flush();
698*6777b538SAndroid Build Coastguard Worker }
699*6777b538SAndroid Build Coastguard Worker 
Flush()700*6777b538SAndroid Build Coastguard Worker void LogMessage::Flush() {
701*6777b538SAndroid Build Coastguard Worker   size_t stack_start = stream_.str().length();
702*6777b538SAndroid Build Coastguard Worker #if !defined(OFFICIAL_BUILD) && !BUILDFLAG(IS_NACL) && !defined(__UCLIBC__) && \
703*6777b538SAndroid Build Coastguard Worker     !BUILDFLAG(IS_AIX)
704*6777b538SAndroid Build Coastguard Worker   // Include a stack trace on a fatal, unless a debugger is attached.
705*6777b538SAndroid Build Coastguard Worker   if (severity_ == LOGGING_FATAL && !base::debug::BeingDebugged()) {
706*6777b538SAndroid Build Coastguard Worker     base::debug::StackTrace stack_trace;
707*6777b538SAndroid Build Coastguard Worker     stream_ << std::endl;  // Newline to separate from log message.
708*6777b538SAndroid Build Coastguard Worker     stack_trace.OutputToStream(&stream_);
709*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
710*6777b538SAndroid Build Coastguard Worker     std::string java_stack = base::android::GetJavaStackTraceIfPresent();
711*6777b538SAndroid Build Coastguard Worker     if (!java_stack.empty()) {
712*6777b538SAndroid Build Coastguard Worker       stream_ << "Java stack (may interleave with native stack):\n";
713*6777b538SAndroid Build Coastguard Worker       stream_ << java_stack << '\n';
714*6777b538SAndroid Build Coastguard Worker     }
715*6777b538SAndroid Build Coastguard Worker #endif
716*6777b538SAndroid Build Coastguard Worker     base::debug::TaskTrace task_trace;
717*6777b538SAndroid Build Coastguard Worker     if (!task_trace.empty())
718*6777b538SAndroid Build Coastguard Worker       task_trace.OutputToStream(&stream_);
719*6777b538SAndroid Build Coastguard Worker 
720*6777b538SAndroid Build Coastguard Worker     // Include the IPC context, if any.
721*6777b538SAndroid Build Coastguard Worker     // TODO(chrisha): Integrate with symbolization once those tools exist!
722*6777b538SAndroid Build Coastguard Worker     const auto* task = base::TaskAnnotator::CurrentTaskForThread();
723*6777b538SAndroid Build Coastguard Worker     if (task && task->ipc_hash) {
724*6777b538SAndroid Build Coastguard Worker       stream_ << "IPC message handler context: "
725*6777b538SAndroid Build Coastguard Worker               << base::StringPrintf("0x%08X", task->ipc_hash) << std::endl;
726*6777b538SAndroid Build Coastguard Worker     }
727*6777b538SAndroid Build Coastguard Worker 
728*6777b538SAndroid Build Coastguard Worker     // Include the crash keys, if any.
729*6777b538SAndroid Build Coastguard Worker     base::debug::OutputCrashKeysToStream(stream_);
730*6777b538SAndroid Build Coastguard Worker   }
731*6777b538SAndroid Build Coastguard Worker #endif
732*6777b538SAndroid Build Coastguard Worker   stream_ << std::endl;
733*6777b538SAndroid Build Coastguard Worker   std::string str_newline(stream_.str());
734*6777b538SAndroid Build Coastguard Worker   TraceLogMessage(file_, line_, str_newline.substr(message_start_));
735*6777b538SAndroid Build Coastguard Worker 
736*6777b538SAndroid Build Coastguard Worker   // FATAL messages should always run the assert handler and crash, even if a
737*6777b538SAndroid Build Coastguard Worker   // message handler marks them as otherwise handled.
738*6777b538SAndroid Build Coastguard Worker   absl::Cleanup handle_fatal_message = [&] {
739*6777b538SAndroid Build Coastguard Worker     if (severity_ == LOGGING_FATAL) {
740*6777b538SAndroid Build Coastguard Worker       HandleFatal(stack_start, str_newline);
741*6777b538SAndroid Build Coastguard Worker     }
742*6777b538SAndroid Build Coastguard Worker   };
743*6777b538SAndroid Build Coastguard Worker 
744*6777b538SAndroid Build Coastguard Worker   if (severity_ == LOGGING_FATAL)
745*6777b538SAndroid Build Coastguard Worker     SetLogFatalCrashKey(this);
746*6777b538SAndroid Build Coastguard Worker 
747*6777b538SAndroid Build Coastguard Worker   // Give any log message handler first dibs on the message.
748*6777b538SAndroid Build Coastguard Worker   if (g_log_message_handler &&
749*6777b538SAndroid Build Coastguard Worker       g_log_message_handler(severity_, file_, line_, message_start_,
750*6777b538SAndroid Build Coastguard Worker                             str_newline)) {
751*6777b538SAndroid Build Coastguard Worker     // The handler took care of it, no further processing.
752*6777b538SAndroid Build Coastguard Worker     return;
753*6777b538SAndroid Build Coastguard Worker   }
754*6777b538SAndroid Build Coastguard Worker 
755*6777b538SAndroid Build Coastguard Worker   if ((g_logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) != 0) {
756*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
757*6777b538SAndroid Build Coastguard Worker     OutputDebugStringA(str_newline.c_str());
758*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_APPLE)
759*6777b538SAndroid Build Coastguard Worker     // In LOG_TO_SYSTEM_DEBUG_LOG mode, log messages are always written to
760*6777b538SAndroid Build Coastguard Worker     // stderr. If stderr is /dev/null, also log via os_log. If there's something
761*6777b538SAndroid Build Coastguard Worker     // weird about stderr, assume that log messages are going nowhere and log
762*6777b538SAndroid Build Coastguard Worker     // via os_log too. Messages logged via os_log show up in Console.app.
763*6777b538SAndroid Build Coastguard Worker     //
764*6777b538SAndroid Build Coastguard Worker     // Programs started by launchd, as UI applications normally are, have had
765*6777b538SAndroid Build Coastguard Worker     // stderr connected to /dev/null since OS X 10.8. Prior to that, stderr was
766*6777b538SAndroid Build Coastguard Worker     // a pipe to launchd, which logged what it received (see log_redirect_fd in
767*6777b538SAndroid Build Coastguard Worker     // 10.7.5 launchd-392.39/launchd/src/launchd_core_logic.c).
768*6777b538SAndroid Build Coastguard Worker     //
769*6777b538SAndroid Build Coastguard Worker     // Another alternative would be to determine whether stderr is a pipe to
770*6777b538SAndroid Build Coastguard Worker     // launchd and avoid logging via os_log only in that case. See 10.7.5
771*6777b538SAndroid Build Coastguard Worker     // CF-635.21/CFUtilities.c also_do_stderr(). This would result in logging to
772*6777b538SAndroid Build Coastguard Worker     // both stderr and os_log even in tests, where it's undesirable to log to
773*6777b538SAndroid Build Coastguard Worker     // the system log at all.
774*6777b538SAndroid Build Coastguard Worker     const bool log_to_system = []() {
775*6777b538SAndroid Build Coastguard Worker       struct stat stderr_stat;
776*6777b538SAndroid Build Coastguard Worker       if (fstat(fileno(stderr), &stderr_stat) == -1) {
777*6777b538SAndroid Build Coastguard Worker         return true;
778*6777b538SAndroid Build Coastguard Worker       }
779*6777b538SAndroid Build Coastguard Worker       if (!S_ISCHR(stderr_stat.st_mode)) {
780*6777b538SAndroid Build Coastguard Worker         return false;
781*6777b538SAndroid Build Coastguard Worker       }
782*6777b538SAndroid Build Coastguard Worker 
783*6777b538SAndroid Build Coastguard Worker       struct stat dev_null_stat;
784*6777b538SAndroid Build Coastguard Worker       if (stat(_PATH_DEVNULL, &dev_null_stat) == -1) {
785*6777b538SAndroid Build Coastguard Worker         return true;
786*6777b538SAndroid Build Coastguard Worker       }
787*6777b538SAndroid Build Coastguard Worker 
788*6777b538SAndroid Build Coastguard Worker       return !S_ISCHR(dev_null_stat.st_mode) ||
789*6777b538SAndroid Build Coastguard Worker              stderr_stat.st_rdev == dev_null_stat.st_rdev;
790*6777b538SAndroid Build Coastguard Worker     }();
791*6777b538SAndroid Build Coastguard Worker 
792*6777b538SAndroid Build Coastguard Worker     if (log_to_system) {
793*6777b538SAndroid Build Coastguard Worker       // Log roughly the same way that CFLog() and NSLog() would. See 10.10.5
794*6777b538SAndroid Build Coastguard Worker       // CF-1153.18/CFUtilities.c __CFLogCString().
795*6777b538SAndroid Build Coastguard Worker       CFBundleRef main_bundle = CFBundleGetMainBundle();
796*6777b538SAndroid Build Coastguard Worker       CFStringRef main_bundle_id_cf =
797*6777b538SAndroid Build Coastguard Worker           main_bundle ? CFBundleGetIdentifier(main_bundle) : nullptr;
798*6777b538SAndroid Build Coastguard Worker       std::string main_bundle_id =
799*6777b538SAndroid Build Coastguard Worker           main_bundle_id_cf ? base::SysCFStringRefToUTF8(main_bundle_id_cf)
800*6777b538SAndroid Build Coastguard Worker                             : std::string("");
801*6777b538SAndroid Build Coastguard Worker 
802*6777b538SAndroid Build Coastguard Worker       const class OSLog {
803*6777b538SAndroid Build Coastguard Worker        public:
804*6777b538SAndroid Build Coastguard Worker         explicit OSLog(const char* subsystem)
805*6777b538SAndroid Build Coastguard Worker             : os_log_(subsystem ? os_log_create(subsystem, "chromium_logging")
806*6777b538SAndroid Build Coastguard Worker                                 : OS_LOG_DEFAULT) {}
807*6777b538SAndroid Build Coastguard Worker         OSLog(const OSLog&) = delete;
808*6777b538SAndroid Build Coastguard Worker         OSLog& operator=(const OSLog&) = delete;
809*6777b538SAndroid Build Coastguard Worker         ~OSLog() {
810*6777b538SAndroid Build Coastguard Worker           if (os_log_ != OS_LOG_DEFAULT) {
811*6777b538SAndroid Build Coastguard Worker             os_release(os_log_);
812*6777b538SAndroid Build Coastguard Worker           }
813*6777b538SAndroid Build Coastguard Worker         }
814*6777b538SAndroid Build Coastguard Worker         os_log_t get() const { return os_log_; }
815*6777b538SAndroid Build Coastguard Worker 
816*6777b538SAndroid Build Coastguard Worker        private:
817*6777b538SAndroid Build Coastguard Worker         os_log_t os_log_;
818*6777b538SAndroid Build Coastguard Worker       } log(main_bundle_id.empty() ? nullptr : main_bundle_id.c_str());
819*6777b538SAndroid Build Coastguard Worker       const os_log_type_t os_log_type = [](LogSeverity severity) {
820*6777b538SAndroid Build Coastguard Worker         switch (severity) {
821*6777b538SAndroid Build Coastguard Worker           case LOGGING_INFO:
822*6777b538SAndroid Build Coastguard Worker             return OS_LOG_TYPE_INFO;
823*6777b538SAndroid Build Coastguard Worker           case LOGGING_WARNING:
824*6777b538SAndroid Build Coastguard Worker             return OS_LOG_TYPE_DEFAULT;
825*6777b538SAndroid Build Coastguard Worker           case LOGGING_ERROR:
826*6777b538SAndroid Build Coastguard Worker             return OS_LOG_TYPE_ERROR;
827*6777b538SAndroid Build Coastguard Worker           case LOGGING_FATAL:
828*6777b538SAndroid Build Coastguard Worker             return OS_LOG_TYPE_FAULT;
829*6777b538SAndroid Build Coastguard Worker           case LOGGING_VERBOSE:
830*6777b538SAndroid Build Coastguard Worker             return OS_LOG_TYPE_DEBUG;
831*6777b538SAndroid Build Coastguard Worker           default:
832*6777b538SAndroid Build Coastguard Worker             return OS_LOG_TYPE_DEFAULT;
833*6777b538SAndroid Build Coastguard Worker         }
834*6777b538SAndroid Build Coastguard Worker       }(severity_);
835*6777b538SAndroid Build Coastguard Worker       os_log_with_type(log.get(), os_log_type, "%{public}s",
836*6777b538SAndroid Build Coastguard Worker                        str_newline.c_str());
837*6777b538SAndroid Build Coastguard Worker     }
838*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_ANDROID)
839*6777b538SAndroid Build Coastguard Worker     android_LogPriority priority =
840*6777b538SAndroid Build Coastguard Worker         (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN;
841*6777b538SAndroid Build Coastguard Worker     switch (severity_) {
842*6777b538SAndroid Build Coastguard Worker       case LOGGING_INFO:
843*6777b538SAndroid Build Coastguard Worker         priority = ANDROID_LOG_INFO;
844*6777b538SAndroid Build Coastguard Worker         break;
845*6777b538SAndroid Build Coastguard Worker       case LOGGING_WARNING:
846*6777b538SAndroid Build Coastguard Worker         priority = ANDROID_LOG_WARN;
847*6777b538SAndroid Build Coastguard Worker         break;
848*6777b538SAndroid Build Coastguard Worker       case LOGGING_ERROR:
849*6777b538SAndroid Build Coastguard Worker         priority = ANDROID_LOG_ERROR;
850*6777b538SAndroid Build Coastguard Worker         break;
851*6777b538SAndroid Build Coastguard Worker       case LOGGING_FATAL:
852*6777b538SAndroid Build Coastguard Worker         priority = ANDROID_LOG_FATAL;
853*6777b538SAndroid Build Coastguard Worker         break;
854*6777b538SAndroid Build Coastguard Worker     }
855*6777b538SAndroid Build Coastguard Worker     const char kAndroidLogTag[] = "chromium";
856*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
857*6777b538SAndroid Build Coastguard Worker     // Split the output by new lines to prevent the Android system from
858*6777b538SAndroid Build Coastguard Worker     // truncating the log.
859*6777b538SAndroid Build Coastguard Worker     std::vector<std::string> lines = base::SplitString(
860*6777b538SAndroid Build Coastguard Worker         str_newline, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
861*6777b538SAndroid Build Coastguard Worker     // str_newline has an extra newline appended to it (at the top of this
862*6777b538SAndroid Build Coastguard Worker     // function), so skip the last split element to avoid needlessly
863*6777b538SAndroid Build Coastguard Worker     // logging an empty string.
864*6777b538SAndroid Build Coastguard Worker     lines.pop_back();
865*6777b538SAndroid Build Coastguard Worker     for (const auto& line : lines)
866*6777b538SAndroid Build Coastguard Worker       __android_log_write(priority, kAndroidLogTag, line.c_str());
867*6777b538SAndroid Build Coastguard Worker #else
868*6777b538SAndroid Build Coastguard Worker     // The Android system may truncate the string if it's too long.
869*6777b538SAndroid Build Coastguard Worker     __android_log_write(priority, kAndroidLogTag, str_newline.c_str());
870*6777b538SAndroid Build Coastguard Worker #endif
871*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_FUCHSIA)
872*6777b538SAndroid Build Coastguard Worker     // LogMessage() will silently drop the message if the logger is not valid.
873*6777b538SAndroid Build Coastguard Worker     // Skip the final character of |str_newline|, since LogMessage() will add
874*6777b538SAndroid Build Coastguard Worker     // a newline.
875*6777b538SAndroid Build Coastguard Worker     const auto message = base::StringPiece(str_newline).substr(message_start_);
876*6777b538SAndroid Build Coastguard Worker     GetScopedFxLogger().LogMessage(file_, static_cast<uint32_t>(line_),
877*6777b538SAndroid Build Coastguard Worker                                    message.substr(0, message.size() - 1),
878*6777b538SAndroid Build Coastguard Worker                                    LogSeverityToFuchsiaLogSeverity(severity_));
879*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_FUCHSIA)
880*6777b538SAndroid Build Coastguard Worker   }
881*6777b538SAndroid Build Coastguard Worker 
882*6777b538SAndroid Build Coastguard Worker   if (ShouldLogToStderr(severity_)) {
883*6777b538SAndroid Build Coastguard Worker     // Not using fwrite() here, as there are crashes on Windows when CRT calls
884*6777b538SAndroid Build Coastguard Worker     // malloc() internally, triggering an OOM crash. This likely means that the
885*6777b538SAndroid Build Coastguard Worker     // process is close to OOM, but at least get the proper error message out,
886*6777b538SAndroid Build Coastguard Worker     // and give the caller a chance to free() up some resources. For instance if
887*6777b538SAndroid Build Coastguard Worker     // the calling code is:
888*6777b538SAndroid Build Coastguard Worker     //
889*6777b538SAndroid Build Coastguard Worker     // allocate_something();
890*6777b538SAndroid Build Coastguard Worker     // if (!TryToDoSomething()) {
891*6777b538SAndroid Build Coastguard Worker     //   LOG(ERROR) << "Something went wrong";
892*6777b538SAndroid Build Coastguard Worker     //   free_something();
893*6777b538SAndroid Build Coastguard Worker     // }
894*6777b538SAndroid Build Coastguard Worker     WriteToFd(STDERR_FILENO, str_newline.data(), str_newline.size());
895*6777b538SAndroid Build Coastguard Worker   }
896*6777b538SAndroid Build Coastguard Worker 
897*6777b538SAndroid Build Coastguard Worker   if ((g_logging_destination & LOG_TO_FILE) != 0) {
898*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
899*6777b538SAndroid Build Coastguard Worker     // If the client app did not call InitLogging() and the lock has not
900*6777b538SAndroid Build Coastguard Worker     // been created it will be done now on calling GetLoggingLock(). We do this
901*6777b538SAndroid Build Coastguard Worker     // on demand, but if two threads try to do this at the same time, there will
902*6777b538SAndroid Build Coastguard Worker     // be a race condition to create the lock. This is why InitLogging should be
903*6777b538SAndroid Build Coastguard Worker     // called from the main thread at the beginning of execution.
904*6777b538SAndroid Build Coastguard Worker     base::AutoLock guard(GetLoggingLock());
905*6777b538SAndroid Build Coastguard Worker #endif
906*6777b538SAndroid Build Coastguard Worker     if (InitializeLogFileHandle()) {
907*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
908*6777b538SAndroid Build Coastguard Worker       DWORD num_written;
909*6777b538SAndroid Build Coastguard Worker       WriteFile(g_log_file,
910*6777b538SAndroid Build Coastguard Worker                 static_cast<const void*>(str_newline.c_str()),
911*6777b538SAndroid Build Coastguard Worker                 static_cast<DWORD>(str_newline.length()),
912*6777b538SAndroid Build Coastguard Worker                 &num_written,
913*6777b538SAndroid Build Coastguard Worker                 nullptr);
914*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
915*6777b538SAndroid Build Coastguard Worker       std::ignore =
916*6777b538SAndroid Build Coastguard Worker           fwrite(str_newline.data(), str_newline.size(), 1, g_log_file);
917*6777b538SAndroid Build Coastguard Worker       fflush(g_log_file);
918*6777b538SAndroid Build Coastguard Worker #else
919*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
920*6777b538SAndroid Build Coastguard Worker #endif
921*6777b538SAndroid Build Coastguard Worker     }
922*6777b538SAndroid Build Coastguard Worker   }
923*6777b538SAndroid Build Coastguard Worker }
924*6777b538SAndroid Build Coastguard Worker 
BuildCrashString() const925*6777b538SAndroid Build Coastguard Worker std::string LogMessage::BuildCrashString() const {
926*6777b538SAndroid Build Coastguard Worker   return logging::BuildCrashString(file(), line(),
927*6777b538SAndroid Build Coastguard Worker                                    str().c_str() + message_start_);
928*6777b538SAndroid Build Coastguard Worker }
929*6777b538SAndroid Build Coastguard Worker 
930*6777b538SAndroid Build Coastguard Worker // writes the common header info to the stream
Init(const char * file,int line)931*6777b538SAndroid Build Coastguard Worker void LogMessage::Init(const char* file, int line) {
932*6777b538SAndroid Build Coastguard Worker   base::StringPiece filename(file);
933*6777b538SAndroid Build Coastguard Worker   size_t last_slash_pos = filename.find_last_of("\\/");
934*6777b538SAndroid Build Coastguard Worker   if (last_slash_pos != base::StringPiece::npos)
935*6777b538SAndroid Build Coastguard Worker     filename.remove_prefix(last_slash_pos + 1);
936*6777b538SAndroid Build Coastguard Worker 
937*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
938*6777b538SAndroid Build Coastguard Worker   if (g_log_format == LogFormat::LOG_FORMAT_SYSLOG) {
939*6777b538SAndroid Build Coastguard Worker     InitWithSyslogPrefix(
940*6777b538SAndroid Build Coastguard Worker         filename, line, TickCount(), log_severity_name(severity_), g_log_prefix,
941*6777b538SAndroid Build Coastguard Worker         g_log_process_id, g_log_thread_id, g_log_timestamp, g_log_tickcount);
942*6777b538SAndroid Build Coastguard Worker   } else
943*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_CHROMEOS)
944*6777b538SAndroid Build Coastguard Worker   {
945*6777b538SAndroid Build Coastguard Worker     // TODO(darin): It might be nice if the columns were fixed width.
946*6777b538SAndroid Build Coastguard Worker     stream_ << '[';
947*6777b538SAndroid Build Coastguard Worker     if (g_log_prefix)
948*6777b538SAndroid Build Coastguard Worker       stream_ << g_log_prefix << ':';
949*6777b538SAndroid Build Coastguard Worker     if (g_log_process_id)
950*6777b538SAndroid Build Coastguard Worker       stream_ << base::GetUniqueIdForProcess() << ':';
951*6777b538SAndroid Build Coastguard Worker     if (g_log_thread_id)
952*6777b538SAndroid Build Coastguard Worker       stream_ << base::PlatformThread::CurrentId() << ':';
953*6777b538SAndroid Build Coastguard Worker     if (g_log_timestamp) {
954*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
955*6777b538SAndroid Build Coastguard Worker       SYSTEMTIME local_time;
956*6777b538SAndroid Build Coastguard Worker       GetLocalTime(&local_time);
957*6777b538SAndroid Build Coastguard Worker       stream_ << std::setfill('0')
958*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << local_time.wMonth
959*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << local_time.wDay
960*6777b538SAndroid Build Coastguard Worker               << '/'
961*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << local_time.wHour
962*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << local_time.wMinute
963*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << local_time.wSecond
964*6777b538SAndroid Build Coastguard Worker               << '.'
965*6777b538SAndroid Build Coastguard Worker               << std::setw(3) << local_time.wMilliseconds
966*6777b538SAndroid Build Coastguard Worker               << ':';
967*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
968*6777b538SAndroid Build Coastguard Worker       timeval tv;
969*6777b538SAndroid Build Coastguard Worker       gettimeofday(&tv, nullptr);
970*6777b538SAndroid Build Coastguard Worker       time_t t = tv.tv_sec;
971*6777b538SAndroid Build Coastguard Worker       struct tm local_time;
972*6777b538SAndroid Build Coastguard Worker       localtime_r(&t, &local_time);
973*6777b538SAndroid Build Coastguard Worker       struct tm* tm_time = &local_time;
974*6777b538SAndroid Build Coastguard Worker       stream_ << std::setfill('0')
975*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << 1 + tm_time->tm_mon
976*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << tm_time->tm_mday
977*6777b538SAndroid Build Coastguard Worker               << '/'
978*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << tm_time->tm_hour
979*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << tm_time->tm_min
980*6777b538SAndroid Build Coastguard Worker               << std::setw(2) << tm_time->tm_sec
981*6777b538SAndroid Build Coastguard Worker               << '.'
982*6777b538SAndroid Build Coastguard Worker               << std::setw(6) << tv.tv_usec
983*6777b538SAndroid Build Coastguard Worker               << ':';
984*6777b538SAndroid Build Coastguard Worker #else
985*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
986*6777b538SAndroid Build Coastguard Worker #endif
987*6777b538SAndroid Build Coastguard Worker     }
988*6777b538SAndroid Build Coastguard Worker     if (g_log_tickcount)
989*6777b538SAndroid Build Coastguard Worker       stream_ << TickCount() << ':';
990*6777b538SAndroid Build Coastguard Worker     if (severity_ >= 0) {
991*6777b538SAndroid Build Coastguard Worker       stream_ << log_severity_name(severity_);
992*6777b538SAndroid Build Coastguard Worker     } else {
993*6777b538SAndroid Build Coastguard Worker       stream_ << "VERBOSE" << -severity_;
994*6777b538SAndroid Build Coastguard Worker     }
995*6777b538SAndroid Build Coastguard Worker     stream_ << ":" << filename << "(" << line << ")] ";
996*6777b538SAndroid Build Coastguard Worker   }
997*6777b538SAndroid Build Coastguard Worker   message_start_ = stream_.str().length();
998*6777b538SAndroid Build Coastguard Worker }
999*6777b538SAndroid Build Coastguard Worker 
HandleFatal(size_t stack_start,const std::string & str_newline) const1000*6777b538SAndroid Build Coastguard Worker void LogMessage::HandleFatal(size_t stack_start,
1001*6777b538SAndroid Build Coastguard Worker                              const std::string& str_newline) const {
1002*6777b538SAndroid Build Coastguard Worker   char str_stack[1024];
1003*6777b538SAndroid Build Coastguard Worker   base::strlcpy(str_stack, str_newline.data(), std::size(str_stack));
1004*6777b538SAndroid Build Coastguard Worker   base::debug::Alias(&str_stack);
1005*6777b538SAndroid Build Coastguard Worker 
1006*6777b538SAndroid Build Coastguard Worker   if (!GetLogAssertHandlerStack().empty()) {
1007*6777b538SAndroid Build Coastguard Worker     LogAssertHandlerFunction log_assert_handler =
1008*6777b538SAndroid Build Coastguard Worker         GetLogAssertHandlerStack().top();
1009*6777b538SAndroid Build Coastguard Worker 
1010*6777b538SAndroid Build Coastguard Worker     if (log_assert_handler) {
1011*6777b538SAndroid Build Coastguard Worker       log_assert_handler.Run(
1012*6777b538SAndroid Build Coastguard Worker           file_, line_,
1013*6777b538SAndroid Build Coastguard Worker           base::StringPiece(str_newline.c_str() + message_start_,
1014*6777b538SAndroid Build Coastguard Worker                             stack_start - message_start_),
1015*6777b538SAndroid Build Coastguard Worker           base::StringPiece(str_newline.c_str() + stack_start));
1016*6777b538SAndroid Build Coastguard Worker     }
1017*6777b538SAndroid Build Coastguard Worker   } else {
1018*6777b538SAndroid Build Coastguard Worker     // Don't use the string with the newline, get a fresh version to send to
1019*6777b538SAndroid Build Coastguard Worker     // the debug message process. We also don't display assertions to the
1020*6777b538SAndroid Build Coastguard Worker     // user in release mode. The enduser can't do anything with this
1021*6777b538SAndroid Build Coastguard Worker     // information, and displaying message boxes when the application is
1022*6777b538SAndroid Build Coastguard Worker     // hosed can cause additional problems.
1023*6777b538SAndroid Build Coastguard Worker #ifndef NDEBUG
1024*6777b538SAndroid Build Coastguard Worker     if (!base::debug::BeingDebugged()) {
1025*6777b538SAndroid Build Coastguard Worker       // Displaying a dialog is unnecessary when debugging and can complicate
1026*6777b538SAndroid Build Coastguard Worker       // debugging.
1027*6777b538SAndroid Build Coastguard Worker       DisplayDebugMessageInDialog(stream_.str());
1028*6777b538SAndroid Build Coastguard Worker     }
1029*6777b538SAndroid Build Coastguard Worker #endif
1030*6777b538SAndroid Build Coastguard Worker 
1031*6777b538SAndroid Build Coastguard Worker     // Crash the process to generate a dump.
1032*6777b538SAndroid Build Coastguard Worker     // TODO(crbug.com/1409729): Move ImmediateCrash() to an absl::Cleanup to
1033*6777b538SAndroid Build Coastguard Worker     // make sure it runs unconditionally. Currently LogAssertHandlers can abort
1034*6777b538SAndroid Build Coastguard Worker     // a FATAL message and tests rely on this. HandleFatal() should be
1035*6777b538SAndroid Build Coastguard Worker     // [[noreturn]].
1036*6777b538SAndroid Build Coastguard Worker     base::ImmediateCrash();
1037*6777b538SAndroid Build Coastguard Worker   }
1038*6777b538SAndroid Build Coastguard Worker }
1039*6777b538SAndroid Build Coastguard Worker 
~LogMessageFatal()1040*6777b538SAndroid Build Coastguard Worker LogMessageFatal::~LogMessageFatal() {
1041*6777b538SAndroid Build Coastguard Worker   Flush();
1042*6777b538SAndroid Build Coastguard Worker   base::ImmediateCrash();
1043*6777b538SAndroid Build Coastguard Worker }
1044*6777b538SAndroid Build Coastguard Worker 
1045*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
1046*6777b538SAndroid Build Coastguard Worker // This has already been defined in the header, but defining it again as DWORD
1047*6777b538SAndroid Build Coastguard Worker // ensures that the type used in the header is equivalent to DWORD. If not,
1048*6777b538SAndroid Build Coastguard Worker // the redefinition is a compile error.
1049*6777b538SAndroid Build Coastguard Worker typedef DWORD SystemErrorCode;
1050*6777b538SAndroid Build Coastguard Worker #endif
1051*6777b538SAndroid Build Coastguard Worker 
GetLastSystemErrorCode()1052*6777b538SAndroid Build Coastguard Worker SystemErrorCode GetLastSystemErrorCode() {
1053*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
1054*6777b538SAndroid Build Coastguard Worker   return ::GetLastError();
1055*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1056*6777b538SAndroid Build Coastguard Worker   return errno;
1057*6777b538SAndroid Build Coastguard Worker #endif
1058*6777b538SAndroid Build Coastguard Worker }
1059*6777b538SAndroid Build Coastguard Worker 
SystemErrorCodeToString(SystemErrorCode error_code)1060*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::string SystemErrorCodeToString(SystemErrorCode error_code) {
1061*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
1062*6777b538SAndroid Build Coastguard Worker   LPWSTR msgbuf = nullptr;
1063*6777b538SAndroid Build Coastguard Worker   DWORD len = ::FormatMessageW(
1064*6777b538SAndroid Build Coastguard Worker       FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
1065*6777b538SAndroid Build Coastguard Worker           FORMAT_MESSAGE_IGNORE_INSERTS,
1066*6777b538SAndroid Build Coastguard Worker       nullptr, error_code, 0, reinterpret_cast<LPWSTR>(&msgbuf), 0, nullptr);
1067*6777b538SAndroid Build Coastguard Worker   if (len) {
1068*6777b538SAndroid Build Coastguard Worker     std::u16string message = base::WideToUTF16(msgbuf);
1069*6777b538SAndroid Build Coastguard Worker     ::LocalFree(msgbuf);
1070*6777b538SAndroid Build Coastguard Worker     msgbuf = nullptr;
1071*6777b538SAndroid Build Coastguard Worker     // Messages returned by system end with line breaks.
1072*6777b538SAndroid Build Coastguard Worker     return base::UTF16ToUTF8(base::CollapseWhitespace(message, true)) +
1073*6777b538SAndroid Build Coastguard Worker            base::StringPrintf(" (0x%lX)", error_code);
1074*6777b538SAndroid Build Coastguard Worker   }
1075*6777b538SAndroid Build Coastguard Worker   return base::StringPrintf("Error (0x%lX) while retrieving error. (0x%lX)",
1076*6777b538SAndroid Build Coastguard Worker                             GetLastError(), error_code);
1077*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1078*6777b538SAndroid Build Coastguard Worker   return base::safe_strerror(error_code) +
1079*6777b538SAndroid Build Coastguard Worker          base::StringPrintf(" (%d)", error_code);
1080*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
1081*6777b538SAndroid Build Coastguard Worker }
1082*6777b538SAndroid Build Coastguard Worker 
1083*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
Win32ErrorLogMessage(const char * file,int line,LogSeverity severity,SystemErrorCode err)1084*6777b538SAndroid Build Coastguard Worker Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file,
1085*6777b538SAndroid Build Coastguard Worker                                            int line,
1086*6777b538SAndroid Build Coastguard Worker                                            LogSeverity severity,
1087*6777b538SAndroid Build Coastguard Worker                                            SystemErrorCode err)
1088*6777b538SAndroid Build Coastguard Worker     : LogMessage(file, line, severity), err_(err) {}
1089*6777b538SAndroid Build Coastguard Worker 
~Win32ErrorLogMessage()1090*6777b538SAndroid Build Coastguard Worker Win32ErrorLogMessage::~Win32ErrorLogMessage() {
1091*6777b538SAndroid Build Coastguard Worker   AppendError();
1092*6777b538SAndroid Build Coastguard Worker }
1093*6777b538SAndroid Build Coastguard Worker 
AppendError()1094*6777b538SAndroid Build Coastguard Worker void Win32ErrorLogMessage::AppendError() {
1095*6777b538SAndroid Build Coastguard Worker   stream() << ": " << SystemErrorCodeToString(err_);
1096*6777b538SAndroid Build Coastguard Worker   // We're about to crash (CHECK). Put |err_| on the stack (by placing it in a
1097*6777b538SAndroid Build Coastguard Worker   // field) and use Alias in hopes that it makes it into crash dumps.
1098*6777b538SAndroid Build Coastguard Worker   DWORD last_error = err_;
1099*6777b538SAndroid Build Coastguard Worker   base::debug::Alias(&last_error);
1100*6777b538SAndroid Build Coastguard Worker }
1101*6777b538SAndroid Build Coastguard Worker 
~Win32ErrorLogMessageFatal()1102*6777b538SAndroid Build Coastguard Worker Win32ErrorLogMessageFatal::~Win32ErrorLogMessageFatal() {
1103*6777b538SAndroid Build Coastguard Worker   AppendError();
1104*6777b538SAndroid Build Coastguard Worker   Flush();
1105*6777b538SAndroid Build Coastguard Worker   base::ImmediateCrash();
1106*6777b538SAndroid Build Coastguard Worker }
1107*6777b538SAndroid Build Coastguard Worker 
1108*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
ErrnoLogMessage(const char * file,int line,LogSeverity severity,SystemErrorCode err)1109*6777b538SAndroid Build Coastguard Worker ErrnoLogMessage::ErrnoLogMessage(const char* file,
1110*6777b538SAndroid Build Coastguard Worker                                  int line,
1111*6777b538SAndroid Build Coastguard Worker                                  LogSeverity severity,
1112*6777b538SAndroid Build Coastguard Worker                                  SystemErrorCode err)
1113*6777b538SAndroid Build Coastguard Worker     : LogMessage(file, line, severity), err_(err) {}
1114*6777b538SAndroid Build Coastguard Worker 
~ErrnoLogMessage()1115*6777b538SAndroid Build Coastguard Worker ErrnoLogMessage::~ErrnoLogMessage() {
1116*6777b538SAndroid Build Coastguard Worker   AppendError();
1117*6777b538SAndroid Build Coastguard Worker }
1118*6777b538SAndroid Build Coastguard Worker 
AppendError()1119*6777b538SAndroid Build Coastguard Worker void ErrnoLogMessage::AppendError() {
1120*6777b538SAndroid Build Coastguard Worker   stream() << ": " << SystemErrorCodeToString(err_);
1121*6777b538SAndroid Build Coastguard Worker   // We're about to crash (CHECK). Put |err_| on the stack (by placing it in a
1122*6777b538SAndroid Build Coastguard Worker   // field) and use Alias in hopes that it makes it into crash dumps.
1123*6777b538SAndroid Build Coastguard Worker   int last_error = err_;
1124*6777b538SAndroid Build Coastguard Worker   base::debug::Alias(&last_error);
1125*6777b538SAndroid Build Coastguard Worker }
1126*6777b538SAndroid Build Coastguard Worker 
~ErrnoLogMessageFatal()1127*6777b538SAndroid Build Coastguard Worker ErrnoLogMessageFatal::~ErrnoLogMessageFatal() {
1128*6777b538SAndroid Build Coastguard Worker   AppendError();
1129*6777b538SAndroid Build Coastguard Worker   Flush();
1130*6777b538SAndroid Build Coastguard Worker   base::ImmediateCrash();
1131*6777b538SAndroid Build Coastguard Worker }
1132*6777b538SAndroid Build Coastguard Worker 
1133*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
1134*6777b538SAndroid Build Coastguard Worker 
CloseLogFile()1135*6777b538SAndroid Build Coastguard Worker void CloseLogFile() {
1136*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1137*6777b538SAndroid Build Coastguard Worker   base::AutoLock guard(GetLoggingLock());
1138*6777b538SAndroid Build Coastguard Worker #endif
1139*6777b538SAndroid Build Coastguard Worker   CloseLogFileUnlocked();
1140*6777b538SAndroid Build Coastguard Worker }
1141*6777b538SAndroid Build Coastguard Worker 
1142*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS_ASH)
DuplicateLogFILE()1143*6777b538SAndroid Build Coastguard Worker FILE* DuplicateLogFILE() {
1144*6777b538SAndroid Build Coastguard Worker   if ((g_logging_destination & LOG_TO_FILE) == 0 || !InitializeLogFileHandle())
1145*6777b538SAndroid Build Coastguard Worker     return nullptr;
1146*6777b538SAndroid Build Coastguard Worker 
1147*6777b538SAndroid Build Coastguard Worker   int log_fd = fileno(g_log_file);
1148*6777b538SAndroid Build Coastguard Worker   if (log_fd == -1)
1149*6777b538SAndroid Build Coastguard Worker     return nullptr;
1150*6777b538SAndroid Build Coastguard Worker   base::ScopedFD dup_fd(dup(log_fd));
1151*6777b538SAndroid Build Coastguard Worker   if (dup_fd == -1)
1152*6777b538SAndroid Build Coastguard Worker     return nullptr;
1153*6777b538SAndroid Build Coastguard Worker   FILE* duplicate = fdopen(dup_fd.get(), "a");
1154*6777b538SAndroid Build Coastguard Worker   if (!duplicate)
1155*6777b538SAndroid Build Coastguard Worker     return nullptr;
1156*6777b538SAndroid Build Coastguard Worker   std::ignore = dup_fd.release();
1157*6777b538SAndroid Build Coastguard Worker   return duplicate;
1158*6777b538SAndroid Build Coastguard Worker }
1159*6777b538SAndroid Build Coastguard Worker #endif
1160*6777b538SAndroid Build Coastguard Worker 
1161*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
DuplicateLogFileHandle()1162*6777b538SAndroid Build Coastguard Worker HANDLE DuplicateLogFileHandle() {
1163*6777b538SAndroid Build Coastguard Worker   // `g_log_file` should only be valid, or nullptr, but be very careful that we
1164*6777b538SAndroid Build Coastguard Worker   // do not duplicate INVALID_HANDLE_VALUE as it aliases the process handle.
1165*6777b538SAndroid Build Coastguard Worker   if (!(g_logging_destination & LOG_TO_FILE) || !g_log_file ||
1166*6777b538SAndroid Build Coastguard Worker       g_log_file == INVALID_HANDLE_VALUE) {
1167*6777b538SAndroid Build Coastguard Worker     return nullptr;
1168*6777b538SAndroid Build Coastguard Worker   }
1169*6777b538SAndroid Build Coastguard Worker   HANDLE duplicate = nullptr;
1170*6777b538SAndroid Build Coastguard Worker   if (!::DuplicateHandle(::GetCurrentProcess(), g_log_file,
1171*6777b538SAndroid Build Coastguard Worker                          ::GetCurrentProcess(), &duplicate, 0,
1172*6777b538SAndroid Build Coastguard Worker                          /*bInheritHandle=*/TRUE, DUPLICATE_SAME_ACCESS)) {
1173*6777b538SAndroid Build Coastguard Worker     return nullptr;
1174*6777b538SAndroid Build Coastguard Worker   }
1175*6777b538SAndroid Build Coastguard Worker   return duplicate;
1176*6777b538SAndroid Build Coastguard Worker }
1177*6777b538SAndroid Build Coastguard Worker #endif
1178*6777b538SAndroid Build Coastguard Worker 
1179*6777b538SAndroid Build Coastguard Worker // Used for testing. Declared in test/scoped_logging_settings.h.
ScopedLoggingSettings()1180*6777b538SAndroid Build Coastguard Worker ScopedLoggingSettings::ScopedLoggingSettings()
1181*6777b538SAndroid Build Coastguard Worker     : min_log_level_(g_min_log_level),
1182*6777b538SAndroid Build Coastguard Worker       logging_destination_(g_logging_destination),
1183*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
1184*6777b538SAndroid Build Coastguard Worker       log_format_(g_log_format),
1185*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1186*6777b538SAndroid Build Coastguard Worker       enable_process_id_(g_log_process_id),
1187*6777b538SAndroid Build Coastguard Worker       enable_thread_id_(g_log_thread_id),
1188*6777b538SAndroid Build Coastguard Worker       enable_timestamp_(g_log_timestamp),
1189*6777b538SAndroid Build Coastguard Worker       enable_tickcount_(g_log_tickcount),
1190*6777b538SAndroid Build Coastguard Worker       log_prefix_(g_log_prefix),
1191*6777b538SAndroid Build Coastguard Worker       message_handler_(g_log_message_handler) {
1192*6777b538SAndroid Build Coastguard Worker   if (g_log_file_name) {
1193*6777b538SAndroid Build Coastguard Worker     log_file_name_ = *g_log_file_name;
1194*6777b538SAndroid Build Coastguard Worker   }
1195*6777b538SAndroid Build Coastguard Worker 
1196*6777b538SAndroid Build Coastguard Worker   // Duplicating |g_log_file| is complex & unnecessary for this test helpers'
1197*6777b538SAndroid Build Coastguard Worker   // use-cases, and so long as |g_log_file_name| is set, it will be re-opened
1198*6777b538SAndroid Build Coastguard Worker   // automatically anyway, when required, so just close the existing one.
1199*6777b538SAndroid Build Coastguard Worker   if (g_log_file) {
1200*6777b538SAndroid Build Coastguard Worker     CHECK(g_log_file_name) << "Un-named |log_file| is not supported.";
1201*6777b538SAndroid Build Coastguard Worker     CloseLogFileUnlocked();
1202*6777b538SAndroid Build Coastguard Worker   }
1203*6777b538SAndroid Build Coastguard Worker }
1204*6777b538SAndroid Build Coastguard Worker 
~ScopedLoggingSettings()1205*6777b538SAndroid Build Coastguard Worker ScopedLoggingSettings::~ScopedLoggingSettings() {
1206*6777b538SAndroid Build Coastguard Worker   // Re-initialize logging via the normal path. This will clean up old file
1207*6777b538SAndroid Build Coastguard Worker   // name and handle state, including re-initializing the VLOG internal state.
1208*6777b538SAndroid Build Coastguard Worker   CHECK(InitLogging({.logging_dest = logging_destination_,
1209*6777b538SAndroid Build Coastguard Worker                      .log_file_path = log_file_name_,
1210*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
1211*6777b538SAndroid Build Coastguard Worker                      .log_format = log_format_
1212*6777b538SAndroid Build Coastguard Worker #endif
1213*6777b538SAndroid Build Coastguard Worker   })) << "~ScopedLoggingSettings() failed to restore settings.";
1214*6777b538SAndroid Build Coastguard Worker 
1215*6777b538SAndroid Build Coastguard Worker   // Restore plain data settings.
1216*6777b538SAndroid Build Coastguard Worker   SetMinLogLevel(min_log_level_);
1217*6777b538SAndroid Build Coastguard Worker   SetLogItems(enable_process_id_, enable_thread_id_, enable_timestamp_,
1218*6777b538SAndroid Build Coastguard Worker               enable_tickcount_);
1219*6777b538SAndroid Build Coastguard Worker   SetLogPrefix(log_prefix_);
1220*6777b538SAndroid Build Coastguard Worker   SetLogMessageHandler(message_handler_);
1221*6777b538SAndroid Build Coastguard Worker }
1222*6777b538SAndroid Build Coastguard Worker 
1223*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_CHROMEOS)
SetLogFormat(LogFormat log_format) const1224*6777b538SAndroid Build Coastguard Worker void ScopedLoggingSettings::SetLogFormat(LogFormat log_format) const {
1225*6777b538SAndroid Build Coastguard Worker   g_log_format = log_format;
1226*6777b538SAndroid Build Coastguard Worker }
1227*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
1228*6777b538SAndroid Build Coastguard Worker 
RawLog(int level,const char * message)1229*6777b538SAndroid Build Coastguard Worker void RawLog(int level, const char* message) {
1230*6777b538SAndroid Build Coastguard Worker   if (level >= g_min_log_level && message) {
1231*6777b538SAndroid Build Coastguard Worker     const size_t message_len = strlen(message);
1232*6777b538SAndroid Build Coastguard Worker     WriteToFd(STDERR_FILENO, message, message_len);
1233*6777b538SAndroid Build Coastguard Worker 
1234*6777b538SAndroid Build Coastguard Worker     if (message_len > 0 && message[message_len - 1] != '\n') {
1235*6777b538SAndroid Build Coastguard Worker       long rv;
1236*6777b538SAndroid Build Coastguard Worker       do {
1237*6777b538SAndroid Build Coastguard Worker         rv = HANDLE_EINTR(write(STDERR_FILENO, "\n", 1));
1238*6777b538SAndroid Build Coastguard Worker         if (rv < 0) {
1239*6777b538SAndroid Build Coastguard Worker           // Give up, nothing we can do now.
1240*6777b538SAndroid Build Coastguard Worker           break;
1241*6777b538SAndroid Build Coastguard Worker         }
1242*6777b538SAndroid Build Coastguard Worker       } while (rv != 1);
1243*6777b538SAndroid Build Coastguard Worker     }
1244*6777b538SAndroid Build Coastguard Worker   }
1245*6777b538SAndroid Build Coastguard Worker 
1246*6777b538SAndroid Build Coastguard Worker   if (level == LOGGING_FATAL)
1247*6777b538SAndroid Build Coastguard Worker     base::ImmediateCrash();
1248*6777b538SAndroid Build Coastguard Worker }
1249*6777b538SAndroid Build Coastguard Worker 
1250*6777b538SAndroid Build Coastguard Worker // This was defined at the beginning of this file.
1251*6777b538SAndroid Build Coastguard Worker #undef write
1252*6777b538SAndroid Build Coastguard Worker 
1253*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
IsLoggingToFileEnabled()1254*6777b538SAndroid Build Coastguard Worker bool IsLoggingToFileEnabled() {
1255*6777b538SAndroid Build Coastguard Worker   return g_logging_destination & LOG_TO_FILE;
1256*6777b538SAndroid Build Coastguard Worker }
1257*6777b538SAndroid Build Coastguard Worker 
GetLogFileFullPath()1258*6777b538SAndroid Build Coastguard Worker std::wstring GetLogFileFullPath() {
1259*6777b538SAndroid Build Coastguard Worker   if (g_log_file_name)
1260*6777b538SAndroid Build Coastguard Worker     return *g_log_file_name;
1261*6777b538SAndroid Build Coastguard Worker   return std::wstring();
1262*6777b538SAndroid Build Coastguard Worker }
1263*6777b538SAndroid Build Coastguard Worker #endif
1264*6777b538SAndroid Build Coastguard Worker 
1265*6777b538SAndroid Build Coastguard Worker // Used for testing. Declared in test/scoped_logging_settings.h.
1266*6777b538SAndroid Build Coastguard Worker ScopedVmoduleSwitches::ScopedVmoduleSwitches() = default;
1267*6777b538SAndroid Build Coastguard Worker 
CreateVlogInfoWithSwitches(const std::string & vmodule_switch)1268*6777b538SAndroid Build Coastguard Worker VlogInfo* ScopedVmoduleSwitches::CreateVlogInfoWithSwitches(
1269*6777b538SAndroid Build Coastguard Worker     const std::string& vmodule_switch) {
1270*6777b538SAndroid Build Coastguard Worker   // Try get a VlogInfo on which to base this.
1271*6777b538SAndroid Build Coastguard Worker   // First ensure that VLOG has been initialized.
1272*6777b538SAndroid Build Coastguard Worker   MaybeInitializeVlogInfo();
1273*6777b538SAndroid Build Coastguard Worker 
1274*6777b538SAndroid Build Coastguard Worker   // Getting this now and setting it later is racy, however if a
1275*6777b538SAndroid Build Coastguard Worker   // ScopedVmoduleSwitches is being used on multiple threads that requires
1276*6777b538SAndroid Build Coastguard Worker   // further coordination and avoids this race.
1277*6777b538SAndroid Build Coastguard Worker   VlogInfo* base_vlog_info = GetVlogInfo();
1278*6777b538SAndroid Build Coastguard Worker   if (!base_vlog_info) {
1279*6777b538SAndroid Build Coastguard Worker     // Base is |nullptr|, so just create it from scratch.
1280*6777b538SAndroid Build Coastguard Worker     return new VlogInfo(/*v_switch_=*/"", vmodule_switch, &g_min_log_level);
1281*6777b538SAndroid Build Coastguard Worker   }
1282*6777b538SAndroid Build Coastguard Worker   return base_vlog_info->WithSwitches(vmodule_switch);
1283*6777b538SAndroid Build Coastguard Worker }
1284*6777b538SAndroid Build Coastguard Worker 
InitWithSwitches(const std::string & vmodule_switch)1285*6777b538SAndroid Build Coastguard Worker void ScopedVmoduleSwitches::InitWithSwitches(
1286*6777b538SAndroid Build Coastguard Worker     const std::string& vmodule_switch) {
1287*6777b538SAndroid Build Coastguard Worker   // Make sure we are only initialized once.
1288*6777b538SAndroid Build Coastguard Worker   CHECK(!scoped_vlog_info_);
1289*6777b538SAndroid Build Coastguard Worker   {
1290*6777b538SAndroid Build Coastguard Worker #if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL)
1291*6777b538SAndroid Build Coastguard Worker     // See comments on |g_vlog_info|.
1292*6777b538SAndroid Build Coastguard Worker     ScopedLeakSanitizerDisabler lsan_disabler;
1293*6777b538SAndroid Build Coastguard Worker #endif  // defined(LEAK_SANITIZER)
1294*6777b538SAndroid Build Coastguard Worker     scoped_vlog_info_ = CreateVlogInfoWithSwitches(vmodule_switch);
1295*6777b538SAndroid Build Coastguard Worker   }
1296*6777b538SAndroid Build Coastguard Worker   previous_vlog_info_ = ExchangeVlogInfo(scoped_vlog_info_);
1297*6777b538SAndroid Build Coastguard Worker }
1298*6777b538SAndroid Build Coastguard Worker 
~ScopedVmoduleSwitches()1299*6777b538SAndroid Build Coastguard Worker ScopedVmoduleSwitches::~ScopedVmoduleSwitches() {
1300*6777b538SAndroid Build Coastguard Worker   VlogInfo* replaced_vlog_info = ExchangeVlogInfo(previous_vlog_info_);
1301*6777b538SAndroid Build Coastguard Worker   // Make sure something didn't replace our scoped VlogInfo while we weren't
1302*6777b538SAndroid Build Coastguard Worker   // looking.
1303*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(replaced_vlog_info, scoped_vlog_info_);
1304*6777b538SAndroid Build Coastguard Worker }
1305*6777b538SAndroid Build Coastguard Worker 
1306*6777b538SAndroid Build Coastguard Worker }  // namespace logging
1307