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 5#include "base/logging.h" 6 7#include <limits.h> 8#include <stdint.h> 9 10#include "base/macros.h" 11#include "build/build_config.h" 12 13#if defined(OS_WIN) 14#include <io.h> 15#include <windows.h> 16#include "base/files/file_path.h" 17#include "base/files/file_util.h" 18typedef HANDLE FileHandle; 19typedef HANDLE MutexHandle; 20// Windows warns on using write(). It prefers _write(). 21#define write(fd, buf, count) _write(fd, buf, static_cast<unsigned int>(count)) 22// Windows doesn't define STDERR_FILENO. Define it here. 23#define STDERR_FILENO 2 24#elif defined(OS_MACOSX) 25#include <asl.h> 26#include <CoreFoundation/CoreFoundation.h> 27#include <mach/mach.h> 28#include <mach/mach_time.h> 29#include <mach-o/dyld.h> 30#elif defined(OS_POSIX) 31#if defined(OS_NACL) 32#include <sys/time.h> // timespec doesn't seem to be in <time.h> 33#else 34#include <sys/syscall.h> 35#endif 36#include <time.h> 37#endif 38 39#if defined(OS_POSIX) 40#include <errno.h> 41#include <paths.h> 42#include <pthread.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <sys/stat.h> 47#include <unistd.h> 48#define MAX_PATH PATH_MAX 49typedef FILE* FileHandle; 50typedef pthread_mutex_t* MutexHandle; 51#endif 52 53#include <algorithm> 54#include <cassert> 55#include <cstring> 56#include <ctime> 57#include <iomanip> 58#include <ostream> 59#include <string> 60 61#include "base/base_switches.h" 62#include "base/command_line.h" 63#include "base/debug/alias.h" 64#include "base/debug/debugger.h" 65#include "base/debug/stack_trace.h" 66#include "base/files/file_path.h" 67#include "base/posix/eintr_wrapper.h" 68#include "base/strings/string_piece.h" 69#include "base/strings/string_util.h" 70#include "base/strings/stringprintf.h" 71#include "base/strings/sys_string_conversions.h" 72#include "base/strings/utf_string_conversions.h" 73#include "base/synchronization/lock_impl.h" 74#include "base/threading/platform_thread.h" 75#include "base/vlog.h" 76#if defined(OS_POSIX) 77#include "base/posix/safe_strerror.h" 78#endif 79 80#if defined(OS_ANDROID) || defined(__ANDROID__) 81#include <android/log.h> 82#endif 83 84namespace logging { 85 86namespace { 87 88VlogInfo* g_vlog_info = nullptr; 89VlogInfo* g_vlog_info_prev = nullptr; 90 91const char* const log_severity_names[LOG_NUM_SEVERITIES] = { 92 "INFO", "WARNING", "ERROR", "FATAL" }; 93 94const char* log_severity_name(int severity) { 95 if (severity >= 0 && severity < LOG_NUM_SEVERITIES) 96 return log_severity_names[severity]; 97 return "UNKNOWN"; 98} 99 100int g_min_log_level = 0; 101 102LoggingDestination g_logging_destination = LOG_DEFAULT; 103 104// For LOG_ERROR and above, always print to stderr. 105const int kAlwaysPrintErrorLevel = LOG_ERROR; 106 107// Which log file to use? This is initialized by InitLogging or 108// will be lazily initialized to the default value when it is 109// first needed. 110#if defined(OS_WIN) 111typedef std::wstring PathString; 112#else 113typedef std::string PathString; 114#endif 115PathString* g_log_file_name = nullptr; 116 117// This file is lazily opened and the handle may be nullptr 118FileHandle g_log_file = nullptr; 119 120// What should be prepended to each message? 121bool g_log_process_id = false; 122bool g_log_thread_id = false; 123bool g_log_timestamp = true; 124bool g_log_tickcount = false; 125 126// Should we pop up fatal debug messages in a dialog? 127bool show_error_dialogs = false; 128 129// An assert handler override specified by the client to be called instead of 130// the debug message dialog and process termination. 131LogAssertHandlerFunction log_assert_handler = nullptr; 132// A log message handler that gets notified of every log message we process. 133LogMessageHandlerFunction log_message_handler = nullptr; 134 135// Helper functions to wrap platform differences. 136 137int32_t CurrentProcessId() { 138#if defined(OS_WIN) 139 return GetCurrentProcessId(); 140#elif defined(OS_POSIX) 141 return getpid(); 142#endif 143} 144 145uint64_t TickCount() { 146#if defined(OS_WIN) 147 return GetTickCount(); 148#elif defined(OS_MACOSX) 149 return mach_absolute_time(); 150#elif defined(OS_NACL) 151 // NaCl sadly does not have _POSIX_TIMERS enabled in sys/features.h 152 // So we have to use clock() for now. 153 return clock(); 154#elif defined(OS_POSIX) 155 struct timespec ts; 156 clock_gettime(CLOCK_MONOTONIC, &ts); 157 158 uint64_t absolute_micro = static_cast<int64_t>(ts.tv_sec) * 1000000 + 159 static_cast<int64_t>(ts.tv_nsec) / 1000; 160 161 return absolute_micro; 162#endif 163} 164 165void DeleteFilePath(const PathString& log_name) { 166#if defined(OS_WIN) 167 DeleteFile(log_name.c_str()); 168#elif defined(OS_NACL) 169 // Do nothing; unlink() isn't supported on NaCl. 170#else 171 unlink(log_name.c_str()); 172#endif 173} 174 175PathString GetDefaultLogFile() { 176#if defined(OS_WIN) 177 // On Windows we use the same path as the exe. 178 wchar_t module_name[MAX_PATH]; 179 GetModuleFileName(nullptr, module_name, MAX_PATH); 180 181 PathString log_name = module_name; 182 PathString::size_type last_backslash = log_name.rfind('\\', log_name.size()); 183 if (last_backslash != PathString::npos) 184 log_name.erase(last_backslash + 1); 185 log_name += L"debug.log"; 186 return log_name; 187#elif defined(OS_POSIX) 188 // On other platforms we just use the current directory. 189 return PathString("debug.log"); 190#endif 191} 192 193// We don't need locks on Windows for atomically appending to files. The OS 194// provides this functionality. 195#if !defined(OS_WIN) 196// This class acts as a wrapper for locking the logging files. 197// LoggingLock::Init() should be called from the main thread before any logging 198// is done. Then whenever logging, be sure to have a local LoggingLock 199// instance on the stack. This will ensure that the lock is unlocked upon 200// exiting the frame. 201// LoggingLocks can not be nested. 202class LoggingLock { 203 public: 204 LoggingLock() { 205 LockLogging(); 206 } 207 208 ~LoggingLock() { 209 UnlockLogging(); 210 } 211 212 static void Init(LogLockingState lock_log, 213 const PathChar* /* new_log_file */) { 214 if (initialized) 215 return; 216 lock_log_file = lock_log; 217 218 if (lock_log_file != LOCK_LOG_FILE) 219 log_lock = new base::internal::LockImpl(); 220 221 initialized = true; 222 } 223 224 private: 225 static void LockLogging() { 226 if (lock_log_file == LOCK_LOG_FILE) { 227#if defined(OS_POSIX) 228 pthread_mutex_lock(&log_mutex); 229#endif 230 } else { 231 // use the lock 232 log_lock->Lock(); 233 } 234 } 235 236 static void UnlockLogging() { 237 if (lock_log_file == LOCK_LOG_FILE) { 238#if defined(OS_POSIX) 239 pthread_mutex_unlock(&log_mutex); 240#endif 241 } else { 242 log_lock->Unlock(); 243 } 244 } 245 246 // The lock is used if log file locking is false. It helps us avoid problems 247 // with multiple threads writing to the log file at the same time. Use 248 // LockImpl directly instead of using Lock, because Lock makes logging calls. 249 static base::internal::LockImpl* log_lock; 250 251 // When we don't use a lock, we are using a global mutex. We need to do this 252 // because LockFileEx is not thread safe. 253#if defined(OS_POSIX) 254 static pthread_mutex_t log_mutex; 255#endif 256 257 static bool initialized; 258 static LogLockingState lock_log_file; 259}; 260 261// static 262bool LoggingLock::initialized = false; 263// static 264base::internal::LockImpl* LoggingLock::log_lock = nullptr; 265// static 266LogLockingState LoggingLock::lock_log_file = LOCK_LOG_FILE; 267 268#if defined(OS_POSIX) 269pthread_mutex_t LoggingLock::log_mutex = PTHREAD_MUTEX_INITIALIZER; 270#endif 271 272#endif // OS_WIN 273 274// Called by logging functions to ensure that |g_log_file| is initialized 275// and can be used for writing. Returns false if the file could not be 276// initialized. |g_log_file| will be nullptr in this case. 277bool InitializeLogFileHandle() { 278 if (g_log_file) 279 return true; 280 281 if (!g_log_file_name) { 282 // Nobody has called InitLogging to specify a debug log file, so here we 283 // initialize the log file name to a default. 284 g_log_file_name = new PathString(GetDefaultLogFile()); 285 } 286 287 if ((g_logging_destination & LOG_TO_FILE) != 0) { 288#if defined(OS_WIN) 289 // The FILE_APPEND_DATA access mask ensures that the file is atomically 290 // appended to across accesses from multiple threads. 291 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364399(v=vs.85).aspx 292 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx 293 g_log_file = CreateFile(g_log_file_name->c_str(), FILE_APPEND_DATA, 294 FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, 295 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); 296 if (g_log_file == INVALID_HANDLE_VALUE || g_log_file == nullptr) { 297 // try the current directory 298 base::FilePath file_path; 299 if (!base::GetCurrentDirectory(&file_path)) 300 return false; 301 302 *g_log_file_name = file_path.Append( 303 FILE_PATH_LITERAL("debug.log")).value(); 304 305 g_log_file = CreateFile(g_log_file_name->c_str(), FILE_APPEND_DATA, 306 FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, 307 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); 308 if (g_log_file == INVALID_HANDLE_VALUE || g_log_file == nullptr) { 309 g_log_file = nullptr; 310 return false; 311 } 312 } 313#elif defined(OS_POSIX) 314 g_log_file = fopen(g_log_file_name->c_str(), "a"); 315 if (g_log_file == nullptr) 316 return false; 317#endif 318 } 319 320 return true; 321} 322 323void CloseFile(FileHandle log) { 324#if defined(OS_WIN) 325 CloseHandle(log); 326#else 327 fclose(log); 328#endif 329} 330 331void CloseLogFileUnlocked() { 332 if (!g_log_file) 333 return; 334 335 CloseFile(g_log_file); 336 g_log_file = nullptr; 337} 338 339} // namespace 340 341LoggingSettings::LoggingSettings() 342 : logging_dest(LOG_DEFAULT), 343 log_file(nullptr), 344 lock_log(LOCK_LOG_FILE), 345 delete_old(APPEND_TO_OLD_LOG_FILE) {} 346 347bool BaseInitLoggingImpl(const LoggingSettings& settings) { 348#if defined(OS_NACL) 349 // Can log only to the system debug log. 350 CHECK_EQ(settings.logging_dest & ~LOG_TO_SYSTEM_DEBUG_LOG, 0); 351#endif 352 if (base::CommandLine::InitializedForCurrentProcess()) { 353 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 354 // Don't bother initializing |g_vlog_info| unless we use one of the 355 // vlog switches. 356 if (command_line->HasSwitch(switches::kV) || 357 command_line->HasSwitch(switches::kVModule)) { 358 // NOTE: If |g_vlog_info| has already been initialized, it might be in use 359 // by another thread. Don't delete the old VLogInfo, just create a second 360 // one. We keep track of both to avoid memory leak warnings. 361 CHECK(!g_vlog_info_prev); 362 g_vlog_info_prev = g_vlog_info; 363 364 g_vlog_info = 365 new VlogInfo(command_line->GetSwitchValueASCII(switches::kV), 366 command_line->GetSwitchValueASCII(switches::kVModule), 367 &g_min_log_level); 368 } 369 } 370 371 g_logging_destination = settings.logging_dest; 372 373 // ignore file options unless logging to file is set. 374 if ((g_logging_destination & LOG_TO_FILE) == 0) 375 return true; 376 377#if !defined(OS_WIN) 378 LoggingLock::Init(settings.lock_log, settings.log_file); 379 LoggingLock logging_lock; 380#endif 381 382 // Calling InitLogging twice or after some log call has already opened the 383 // default log file will re-initialize to the new options. 384 CloseLogFileUnlocked(); 385 386 if (!g_log_file_name) 387 g_log_file_name = new PathString(); 388 *g_log_file_name = settings.log_file; 389 if (settings.delete_old == DELETE_OLD_LOG_FILE) 390 DeleteFilePath(*g_log_file_name); 391 392 return InitializeLogFileHandle(); 393} 394 395void SetMinLogLevel(int level) { 396 g_min_log_level = std::min(LOG_FATAL, level); 397} 398 399int GetMinLogLevel() { 400 return g_min_log_level; 401} 402 403bool ShouldCreateLogMessage(int severity) { 404 if (severity < g_min_log_level) 405 return false; 406 407 // Return true here unless we know ~LogMessage won't do anything. Note that 408 // ~LogMessage writes to stderr if severity_ >= kAlwaysPrintErrorLevel, even 409 // when g_logging_destination is LOG_NONE. 410 return g_logging_destination != LOG_NONE || log_message_handler || 411 severity >= kAlwaysPrintErrorLevel; 412} 413 414int GetVlogVerbosity() { 415 return std::max(-1, LOG_INFO - GetMinLogLevel()); 416} 417 418int GetVlogLevelHelper(const char* file, size_t N) { 419 DCHECK_GT(N, 0U); 420 // Note: |g_vlog_info| may change on a different thread during startup 421 // (but will always be valid or nullptr). 422 VlogInfo* vlog_info = g_vlog_info; 423 return vlog_info ? 424 vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) : 425 GetVlogVerbosity(); 426} 427 428void SetLogItems(bool enable_process_id, bool enable_thread_id, 429 bool enable_timestamp, bool enable_tickcount) { 430 g_log_process_id = enable_process_id; 431 g_log_thread_id = enable_thread_id; 432 g_log_timestamp = enable_timestamp; 433 g_log_tickcount = enable_tickcount; 434} 435 436void SetShowErrorDialogs(bool enable_dialogs) { 437 show_error_dialogs = enable_dialogs; 438} 439 440void SetLogAssertHandler(LogAssertHandlerFunction handler) { 441 log_assert_handler = handler; 442} 443 444void SetLogMessageHandler(LogMessageHandlerFunction handler) { 445 log_message_handler = handler; 446} 447 448LogMessageHandlerFunction GetLogMessageHandler() { 449 return log_message_handler; 450} 451 452// Explicit instantiations for commonly used comparisons. 453template std::string* MakeCheckOpString<int, int>( 454 const int&, const int&, const char* names); 455template std::string* MakeCheckOpString<unsigned long, unsigned long>( 456 const unsigned long&, const unsigned long&, const char* names); 457template std::string* MakeCheckOpString<unsigned long, unsigned int>( 458 const unsigned long&, const unsigned int&, const char* names); 459template std::string* MakeCheckOpString<unsigned int, unsigned long>( 460 const unsigned int&, const unsigned long&, const char* names); 461template std::string* MakeCheckOpString<std::string, std::string>( 462 const std::string&, const std::string&, const char* name); 463 464#if !defined(NDEBUG) 465// Displays a message box to the user with the error message in it. 466// Used for fatal messages, where we close the app simultaneously. 467// This is for developers only; we don't use this in circumstances 468// (like release builds) where users could see it, since users don't 469// understand these messages anyway. 470void DisplayDebugMessageInDialog(const std::string& str) { 471 if (str.empty()) 472 return; 473 474 if (!show_error_dialogs) 475 return; 476 477#if defined(OS_WIN) 478 MessageBoxW(nullptr, base::UTF8ToUTF16(str).c_str(), L"Fatal error", 479 MB_OK | MB_ICONHAND | MB_TOPMOST); 480#else 481 // We intentionally don't implement a dialog on other platforms. 482 // You can just look at stderr. 483#endif // defined(OS_WIN) 484} 485#endif // !defined(NDEBUG) 486 487#if defined(OS_WIN) 488LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) { 489} 490 491LogMessage::SaveLastError::~SaveLastError() { 492 ::SetLastError(last_error_); 493} 494#endif // defined(OS_WIN) 495 496LogMessage::LogMessage(const char* file, int line, LogSeverity severity) 497 : severity_(severity), file_(file), line_(line) { 498 Init(file, line); 499} 500 501LogMessage::LogMessage(const char* file, int line, const char* condition) 502 : severity_(LOG_FATAL), file_(file), line_(line) { 503 Init(file, line); 504 stream_ << "Check failed: " << condition << ". "; 505} 506 507LogMessage::LogMessage(const char* file, int line, std::string* result) 508 : severity_(LOG_FATAL), file_(file), line_(line) { 509 Init(file, line); 510 stream_ << "Check failed: " << *result; 511 delete result; 512} 513 514LogMessage::LogMessage(const char* file, int line, LogSeverity severity, 515 std::string* result) 516 : severity_(severity), file_(file), line_(line) { 517 Init(file, line); 518 stream_ << "Check failed: " << *result; 519 delete result; 520} 521 522LogMessage::~LogMessage() { 523#if !defined(OFFICIAL_BUILD) && !defined(OS_NACL) && !defined(__UCLIBC__) 524 if (severity_ == LOG_FATAL && !base::debug::BeingDebugged()) { 525 // Include a stack trace on a fatal, unless a debugger is attached. 526 base::debug::StackTrace trace; 527 stream_ << std::endl; // Newline to separate from log message. 528 trace.OutputToStream(&stream_); 529 } 530#endif 531 stream_ << std::endl; 532 std::string str_newline(stream_.str()); 533 534 // Give any log message handler first dibs on the message. 535 if (log_message_handler && 536 log_message_handler(severity_, file_, line_, 537 message_start_, str_newline)) { 538 // The handler took care of it, no further processing. 539 return; 540 } 541 542 if ((g_logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) != 0) { 543#if defined(OS_WIN) 544 OutputDebugStringA(str_newline.c_str()); 545#elif defined(OS_MACOSX) 546 // In LOG_TO_SYSTEM_DEBUG_LOG mode, log messages are always written to 547 // stderr. If stderr is /dev/null, also log via ASL (Apple System Log). If 548 // there's something weird about stderr, assume that log messages are going 549 // nowhere and log via ASL too. Messages logged via ASL show up in 550 // Console.app. 551 // 552 // Programs started by launchd, as UI applications normally are, have had 553 // stderr connected to /dev/null since OS X 10.8. Prior to that, stderr was 554 // a pipe to launchd, which logged what it received (see log_redirect_fd in 555 // 10.7.5 launchd-392.39/launchd/src/launchd_core_logic.c). 556 // 557 // Another alternative would be to determine whether stderr is a pipe to 558 // launchd and avoid logging via ASL only in that case. See 10.7.5 559 // CF-635.21/CFUtilities.c also_do_stderr(). This would result in logging to 560 // both stderr and ASL even in tests, where it's undesirable to log to the 561 // system log at all. 562 // 563 // Note that the ASL client by default discards messages whose levels are 564 // below ASL_LEVEL_NOTICE. It's possible to change that with 565 // asl_set_filter(), but this is pointless because syslogd normally applies 566 // the same filter. 567 const bool log_via_asl = []() { 568 struct stat stderr_stat; 569 if (fstat(fileno(stderr), &stderr_stat) == -1) { 570 return true; 571 } 572 if (!S_ISCHR(stderr_stat.st_mode)) { 573 return false; 574 } 575 576 struct stat dev_null_stat; 577 if (stat(_PATH_DEVNULL, &dev_null_stat) == -1) { 578 return true; 579 } 580 581 return !S_ISCHR(dev_null_stat.st_mode) || 582 stderr_stat.st_rdev == dev_null_stat.st_rdev; 583 }(); 584 585 if (log_via_asl) { 586 // Log roughly the same way that CFLog() and NSLog() would. See 10.10.5 587 // CF-1153.18/CFUtilities.c __CFLogCString(). 588 // 589 // The ASL facility is set to the main bundle ID if available. Otherwise, 590 // "com.apple.console" is used. 591 CFBundleRef main_bundle = CFBundleGetMainBundle(); 592 CFStringRef main_bundle_id_cf = 593 main_bundle ? CFBundleGetIdentifier(main_bundle) : nullptr; 594 std::string asl_facility = 595 main_bundle_id_cf ? base::SysCFStringRefToUTF8(main_bundle_id_cf) 596 : std::string("com.apple.console"); 597 598 class ASLClient { 599 public: 600 explicit ASLClient(const std::string& asl_facility) 601 : client_(asl_open(nullptr, 602 asl_facility.c_str(), 603 ASL_OPT_NO_DELAY)) {} 604 ~ASLClient() { asl_close(client_); } 605 606 aslclient get() const { return client_; } 607 608 private: 609 aslclient client_; 610 DISALLOW_COPY_AND_ASSIGN(ASLClient); 611 } asl_client(asl_facility); 612 613 class ASLMessage { 614 public: 615 ASLMessage() : message_(asl_new(ASL_TYPE_MSG)) {} 616 ~ASLMessage() { asl_free(message_); } 617 618 aslmsg get() const { return message_; } 619 620 private: 621 aslmsg message_; 622 DISALLOW_COPY_AND_ASSIGN(ASLMessage); 623 } asl_message; 624 625 // By default, messages are only readable by the admin group. Explicitly 626 // make them readable by the user generating the messages. 627 char euid_string[12]; 628 snprintf(euid_string, arraysize(euid_string), "%d", geteuid()); 629 asl_set(asl_message.get(), ASL_KEY_READ_UID, euid_string); 630 631 // Map Chrome log severities to ASL log levels. 632 const char* const asl_level_string = [](LogSeverity severity) { 633 // ASL_LEVEL_* are ints, but ASL needs equivalent strings. This 634 // non-obvious two-step macro trick achieves what's needed. 635 // https://gcc.gnu.org/onlinedocs/cpp/Stringification.html 636#define ASL_LEVEL_STR(level) ASL_LEVEL_STR_X(level) 637#define ASL_LEVEL_STR_X(level) #level 638 switch (severity) { 639 case LOG_INFO: 640 return ASL_LEVEL_STR(ASL_LEVEL_INFO); 641 case LOG_WARNING: 642 return ASL_LEVEL_STR(ASL_LEVEL_WARNING); 643 case LOG_ERROR: 644 return ASL_LEVEL_STR(ASL_LEVEL_ERR); 645 case LOG_FATAL: 646 return ASL_LEVEL_STR(ASL_LEVEL_CRIT); 647 default: 648 return severity < 0 ? ASL_LEVEL_STR(ASL_LEVEL_DEBUG) 649 : ASL_LEVEL_STR(ASL_LEVEL_NOTICE); 650 } 651#undef ASL_LEVEL_STR 652#undef ASL_LEVEL_STR_X 653 }(severity_); 654 asl_set(asl_message.get(), ASL_KEY_LEVEL, asl_level_string); 655 656 asl_set(asl_message.get(), ASL_KEY_MSG, str_newline.c_str()); 657 658 asl_send(asl_client.get(), asl_message.get()); 659 } 660#elif defined(OS_ANDROID) || defined(__ANDROID__) 661 android_LogPriority priority = 662 (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN; 663 switch (severity_) { 664 case LOG_INFO: 665 priority = ANDROID_LOG_INFO; 666 break; 667 case LOG_WARNING: 668 priority = ANDROID_LOG_WARN; 669 break; 670 case LOG_ERROR: 671 priority = ANDROID_LOG_ERROR; 672 break; 673 case LOG_FATAL: 674 priority = ANDROID_LOG_FATAL; 675 break; 676 } 677#if defined(OS_ANDROID) 678 __android_log_write(priority, "chromium", str_newline.c_str()); 679#else 680 __android_log_write( 681 priority, 682 base::CommandLine::InitializedForCurrentProcess() ? 683 base::CommandLine::ForCurrentProcess()-> 684 GetProgram().BaseName().value().c_str() : nullptr, 685 str_newline.c_str()); 686#endif // defined(OS_ANDROID) 687#endif 688 ignore_result(fwrite(str_newline.data(), str_newline.size(), 1, stderr)); 689 fflush(stderr); 690 } else if (severity_ >= kAlwaysPrintErrorLevel) { 691 // When we're only outputting to a log file, above a certain log level, we 692 // should still output to stderr so that we can better detect and diagnose 693 // problems with unit tests, especially on the buildbots. 694 ignore_result(fwrite(str_newline.data(), str_newline.size(), 1, stderr)); 695 fflush(stderr); 696 } 697 698 // write to log file 699 if ((g_logging_destination & LOG_TO_FILE) != 0) { 700 // We can have multiple threads and/or processes, so try to prevent them 701 // from clobbering each other's writes. 702 // If the client app did not call InitLogging, and the lock has not 703 // been created do it now. We do this on demand, but if two threads try 704 // to do this at the same time, there will be a race condition to create 705 // the lock. This is why InitLogging should be called from the main 706 // thread at the beginning of execution. 707#if !defined(OS_WIN) 708 LoggingLock::Init(LOCK_LOG_FILE, nullptr); 709 LoggingLock logging_lock; 710#endif 711 if (InitializeLogFileHandle()) { 712#if defined(OS_WIN) 713 DWORD num_written; 714 WriteFile(g_log_file, 715 static_cast<const void*>(str_newline.c_str()), 716 static_cast<DWORD>(str_newline.length()), 717 &num_written, 718 nullptr); 719#else 720 ignore_result(fwrite( 721 str_newline.data(), str_newline.size(), 1, g_log_file)); 722 fflush(g_log_file); 723#endif 724 } 725 } 726 727 if (severity_ == LOG_FATAL) { 728 // Ensure the first characters of the string are on the stack so they 729 // are contained in minidumps for diagnostic purposes. 730 char str_stack[1024]; 731 str_newline.copy(str_stack, arraysize(str_stack)); 732 base::debug::Alias(str_stack); 733 734 if (log_assert_handler) { 735 // Make a copy of the string for the handler out of paranoia. 736 log_assert_handler(std::string(stream_.str())); 737 } else { 738 // Don't use the string with the newline, get a fresh version to send to 739 // the debug message process. We also don't display assertions to the 740 // user in release mode. The enduser can't do anything with this 741 // information, and displaying message boxes when the application is 742 // hosed can cause additional problems. 743#ifndef NDEBUG 744 if (!base::debug::BeingDebugged()) { 745 // Displaying a dialog is unnecessary when debugging and can complicate 746 // debugging. 747 DisplayDebugMessageInDialog(stream_.str()); 748 } 749#endif 750 // Crash the process to generate a dump. 751 base::debug::BreakDebugger(); 752 } 753 } 754} 755 756// writes the common header info to the stream 757void LogMessage::Init(const char* file, int line) { 758 base::StringPiece filename(file); 759 size_t last_slash_pos = filename.find_last_of("\\/"); 760 if (last_slash_pos != base::StringPiece::npos) 761 filename.remove_prefix(last_slash_pos + 1); 762 763 // TODO(darin): It might be nice if the columns were fixed width. 764 765 stream_ << '['; 766 if (g_log_process_id) 767 stream_ << CurrentProcessId() << ':'; 768 if (g_log_thread_id) 769 stream_ << base::PlatformThread::CurrentId() << ':'; 770 if (g_log_timestamp) { 771 time_t t = time(nullptr); 772 struct tm local_time; 773 memset(&local_time, 0, sizeof(local_time)); 774#ifdef _MSC_VER 775 localtime_s(&local_time, &t); 776#else 777 localtime_r(&t, &local_time); 778#endif 779 struct tm* tm_time = &local_time; 780 stream_ << std::setfill('0') 781 << std::setw(2) << 1 + tm_time->tm_mon 782 << std::setw(2) << tm_time->tm_mday 783 << '/' 784 << std::setw(2) << tm_time->tm_hour 785 << std::setw(2) << tm_time->tm_min 786 << std::setw(2) << tm_time->tm_sec 787 << ':'; 788 } 789 if (g_log_tickcount) 790 stream_ << TickCount() << ':'; 791 if (severity_ >= 0) 792 stream_ << log_severity_name(severity_); 793 else 794 stream_ << "VERBOSE" << -severity_; 795 796 stream_ << ":" << filename << "(" << line << ")] "; 797 798 message_start_ = stream_.str().length(); 799} 800 801#if defined(OS_WIN) 802// This has already been defined in the header, but defining it again as DWORD 803// ensures that the type used in the header is equivalent to DWORD. If not, 804// the redefinition is a compile error. 805typedef DWORD SystemErrorCode; 806#endif 807 808SystemErrorCode GetLastSystemErrorCode() { 809#if defined(OS_WIN) 810 return ::GetLastError(); 811#elif defined(OS_POSIX) 812 return errno; 813#else 814#error Not implemented 815#endif 816} 817 818#if defined(OS_WIN) 819BASE_EXPORT std::string SystemErrorCodeToString(SystemErrorCode error_code) { 820 const int kErrorMessageBufferSize = 256; 821 char msgbuf[kErrorMessageBufferSize]; 822 DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; 823 DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf, 824 arraysize(msgbuf), nullptr); 825 if (len) { 826 // Messages returned by system end with line breaks. 827 return base::CollapseWhitespaceASCII(msgbuf, true) + 828 base::StringPrintf(" (0x%X)", error_code); 829 } 830 return base::StringPrintf("Error (0x%X) while retrieving error. (0x%X)", 831 GetLastError(), error_code); 832} 833#elif defined(OS_POSIX) 834BASE_EXPORT std::string SystemErrorCodeToString(SystemErrorCode error_code) { 835 return base::safe_strerror(error_code); 836} 837#else 838#error Not implemented 839#endif // defined(OS_WIN) 840 841 842#if defined(OS_WIN) 843Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, 844 int line, 845 LogSeverity severity, 846 SystemErrorCode err) 847 : err_(err), 848 log_message_(file, line, severity) { 849} 850 851Win32ErrorLogMessage::~Win32ErrorLogMessage() { 852 stream() << ": " << SystemErrorCodeToString(err_); 853 // We're about to crash (CHECK). Put |err_| on the stack (by placing it in a 854 // field) and use Alias in hopes that it makes it into crash dumps. 855 DWORD last_error = err_; 856 base::debug::Alias(&last_error); 857} 858#elif defined(OS_POSIX) 859ErrnoLogMessage::ErrnoLogMessage(const char* file, 860 int line, 861 LogSeverity severity, 862 SystemErrorCode err) 863 : err_(err), 864 log_message_(file, line, severity) { 865} 866 867ErrnoLogMessage::~ErrnoLogMessage() { 868 stream() << ": " << SystemErrorCodeToString(err_); 869} 870#endif // defined(OS_WIN) 871 872void CloseLogFile() { 873#if !defined(OS_WIN) 874 LoggingLock logging_lock; 875#endif 876 CloseLogFileUnlocked(); 877} 878 879void RawLog(int level, const char* message) { 880 if (level >= g_min_log_level) { 881 size_t bytes_written = 0; 882 const size_t message_len = strlen(message); 883 int rv; 884 while (bytes_written < message_len) { 885 rv = HANDLE_EINTR( 886 write(STDERR_FILENO, message + bytes_written, 887 message_len - bytes_written)); 888 if (rv < 0) { 889 // Give up, nothing we can do now. 890 break; 891 } 892 bytes_written += rv; 893 } 894 895 if (message_len > 0 && message[message_len - 1] != '\n') { 896 do { 897 rv = HANDLE_EINTR(write(STDERR_FILENO, "\n", 1)); 898 if (rv < 0) { 899 // Give up, nothing we can do now. 900 break; 901 } 902 } while (rv != 1); 903 } 904 } 905 906 if (level == LOG_FATAL) 907 base::debug::BreakDebugger(); 908} 909 910// This was defined at the beginning of this file. 911#undef write 912 913#if defined(OS_WIN) 914bool IsLoggingToFileEnabled() { 915 return g_logging_destination & LOG_TO_FILE; 916} 917 918std::wstring GetLogFileFullPath() { 919 if (g_log_file_name) 920 return *g_log_file_name; 921 return std::wstring(); 922} 923#endif 924 925BASE_EXPORT void LogErrorNotReached(const char* file, int line) { 926 LogMessage(file, line, LOG_ERROR).stream() 927 << "NOTREACHED() hit."; 928} 929 930} // namespace logging 931 932std::ostream& std::operator<<(std::ostream& out, const wchar_t* wstr) { 933 return out << base::WideToUTF8(wstr); 934} 935