logging.cc 42 KB

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