logging.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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#if defined(OS_WIN) 8#include <io.h> 9#include <windows.h> 10typedef HANDLE FileHandle; 11typedef HANDLE MutexHandle; 12// Windows warns on using write(). It prefers _write(). 13#define write(fd, buf, count) _write(fd, buf, static_cast<unsigned int>(count)) 14// Windows doesn't define STDERR_FILENO. Define it here. 15#define STDERR_FILENO 2 16#elif defined(OS_MACOSX) 17#include <CoreFoundation/CoreFoundation.h> 18#include <mach/mach.h> 19#include <mach/mach_time.h> 20#include <mach-o/dyld.h> 21#elif defined(OS_POSIX) 22#include <sys/syscall.h> 23#include <time.h> 24#endif 25 26#if defined(OS_POSIX) 27#include <errno.h> 28#include <pthread.h> 29#include <stdlib.h> 30#include <stdio.h> 31#include <string.h> 32#include <unistd.h> 33#define MAX_PATH PATH_MAX 34typedef FILE* FileHandle; 35#include "pthread.h" 36typedef pthread_mutex_t* MutexHandle; 37#endif 38 39#include <ctime> 40#include <iomanip> 41#include <cstring> 42#include <algorithm> 43 44#include "base/base_switches.h" 45#include "base/command_line.h" 46#include "base/debug_util.h" 47#include "base/eintr_wrapper.h" 48#include "base/lock_impl.h" 49#if defined(OS_POSIX) 50#include "base/safe_strerror_posix.h" 51#endif 52#include "base/process_util.h" 53#include "base/string_piece.h" 54#include "base/utf_string_conversions.h" 55#include "base/vlog.h" 56 57namespace logging { 58 59bool g_enable_dcheck = false; 60VlogInfo* g_vlog_info = NULL; 61 62const char* const log_severity_names[LOG_NUM_SEVERITIES] = { 63 "INFO", "WARNING", "ERROR", "ERROR_REPORT", "FATAL" }; 64 65int min_log_level = 0; 66 67// The default set here for logging_destination will only be used if 68// InitLogging is not called. On Windows, use a file next to the exe; 69// on POSIX platforms, where it may not even be possible to locate the 70// executable on disk, use stderr. 71#if defined(OS_WIN) 72LoggingDestination logging_destination = LOG_ONLY_TO_FILE; 73#elif defined(OS_POSIX) 74LoggingDestination logging_destination = LOG_ONLY_TO_SYSTEM_DEBUG_LOG; 75#endif 76 77const int kMaxFilteredLogLevel = LOG_WARNING; 78std::string* log_filter_prefix; 79 80// For LOG_ERROR and above, always print to stderr. 81const int kAlwaysPrintErrorLevel = LOG_ERROR; 82 83// Which log file to use? This is initialized by InitLogging or 84// will be lazily initialized to the default value when it is 85// first needed. 86#if defined(OS_WIN) 87typedef std::wstring PathString; 88#else 89typedef std::string PathString; 90#endif 91PathString* log_file_name = NULL; 92 93// this file is lazily opened and the handle may be NULL 94FileHandle log_file = NULL; 95 96// what should be prepended to each message? 97bool log_process_id = false; 98bool log_thread_id = false; 99bool log_timestamp = true; 100bool log_tickcount = false; 101 102// Should we pop up fatal debug messages in a dialog? 103bool show_error_dialogs = false; 104 105// An assert handler override specified by the client to be called instead of 106// the debug message dialog and process termination. 107LogAssertHandlerFunction log_assert_handler = NULL; 108// An report handler override specified by the client to be called instead of 109// the debug message dialog. 110LogReportHandlerFunction log_report_handler = NULL; 111// A log message handler that gets notified of every log message we process. 112LogMessageHandlerFunction log_message_handler = NULL; 113 114// Helper functions to wrap platform differences. 115 116int32 CurrentProcessId() { 117#if defined(OS_WIN) 118 return GetCurrentProcessId(); 119#elif defined(OS_POSIX) 120 return getpid(); 121#endif 122} 123 124int32 CurrentThreadId() { 125#if defined(OS_WIN) 126 return GetCurrentThreadId(); 127#elif defined(OS_MACOSX) 128 return mach_thread_self(); 129#elif defined(OS_LINUX) 130 return syscall(__NR_gettid); 131#elif defined(OS_FREEBSD) 132 // TODO(BSD): find a better thread ID 133 return reinterpret_cast<int64>(pthread_self()); 134#endif 135} 136 137uint64 TickCount() { 138#if defined(OS_WIN) 139 return GetTickCount(); 140#elif defined(OS_MACOSX) 141 return mach_absolute_time(); 142#elif defined(OS_POSIX) 143 struct timespec ts; 144 clock_gettime(CLOCK_MONOTONIC, &ts); 145 146 uint64 absolute_micro = 147 static_cast<int64>(ts.tv_sec) * 1000000 + 148 static_cast<int64>(ts.tv_nsec) / 1000; 149 150 return absolute_micro; 151#endif 152} 153 154void CloseFile(FileHandle log) { 155#if defined(OS_WIN) 156 CloseHandle(log); 157#else 158 fclose(log); 159#endif 160} 161 162void DeleteFilePath(const PathString& log_name) { 163#if defined(OS_WIN) 164 DeleteFile(log_name.c_str()); 165#else 166 unlink(log_name.c_str()); 167#endif 168} 169 170void GetDefaultLogFile(PathString default_log_file) { 171#if defined(OS_WIN) 172 // On Windows we use the same path as the exe. 173 wchar_t module_name[MAX_PATH]; 174 GetModuleFileName(NULL, module_name, MAX_PATH); 175 default_log_file = module_name; 176 std::wstring::size_type last_backslash = 177 default_log_file.rfind('\\', default_log_file.size()); 178 if (last_backslash != std::wstring::npos) 179 default_log_file.erase(last_backslash + 1); 180 default_log_file += L"debug.log"; 181#elif defined(OS_POSIX) 182 // On other platforms we just use the current directory. 183 default_log_file = "debug.log"; 184#endif 185} 186 187// This class acts as a wrapper for locking the logging files. 188// LoggingLock::Init() should be called from the main thread before any logging 189// is done. Then whenever logging, be sure to have a local LoggingLock 190// instance on the stack. This will ensure that the lock is unlocked upon 191// exiting the frame. 192// LoggingLocks can not be nested. 193class LoggingLock { 194 public: 195 LoggingLock() { 196 LockLogging(); 197 } 198 199 ~LoggingLock() { 200 UnlockLogging(); 201 } 202 203 static void Init(LogLockingState lock_log, const PathChar* new_log_file) { 204 if (initialized) 205 return; 206 lock_log_file = lock_log; 207 if (lock_log_file == LOCK_LOG_FILE) { 208#if defined(OS_WIN) 209 if (!log_mutex) { 210 std::wstring safe_name; 211 if (new_log_file) 212 safe_name = new_log_file; 213 else 214 GetDefaultLogFile(safe_name); 215 // \ is not a legal character in mutex names so we replace \ with / 216 std::replace(safe_name.begin(), safe_name.end(), '\\', '/'); 217 std::wstring t(L"Global\\"); 218 t.append(safe_name); 219 log_mutex = ::CreateMutex(NULL, FALSE, t.c_str()); 220 } 221#endif 222 } else { 223 log_lock = new LockImpl(); 224 } 225 initialized = true; 226 } 227 228 private: 229 static void LockLogging() { 230 if (lock_log_file == LOCK_LOG_FILE) { 231#if defined(OS_WIN) 232 ::WaitForSingleObject(log_mutex, INFINITE); 233 // WaitForSingleObject could have returned WAIT_ABANDONED. We don't 234 // abort the process here. UI tests might be crashy sometimes, 235 // and aborting the test binary only makes the problem worse. 236 // We also don't use LOG macros because that might lead to an infinite 237 // loop. For more info see http://crbug.com/18028. 238#elif defined(OS_POSIX) 239 pthread_mutex_lock(&log_mutex); 240#endif 241 } else { 242 // use the lock 243 log_lock->Lock(); 244 } 245 } 246 247 static void UnlockLogging() { 248 if (lock_log_file == LOCK_LOG_FILE) { 249#if defined(OS_WIN) 250 ReleaseMutex(log_mutex); 251#elif defined(OS_POSIX) 252 pthread_mutex_unlock(&log_mutex); 253#endif 254 } else { 255 log_lock->Unlock(); 256 } 257 } 258 259 // The lock is used if log file locking is false. It helps us avoid problems 260 // with multiple threads writing to the log file at the same time. Use 261 // LockImpl directly instead of using Lock, because Lock makes logging calls. 262 static LockImpl* log_lock; 263 264 // When we don't use a lock, we are using a global mutex. We need to do this 265 // because LockFileEx is not thread safe. 266#if defined(OS_WIN) 267 static MutexHandle log_mutex; 268#elif defined(OS_POSIX) 269 static pthread_mutex_t log_mutex; 270#endif 271 272 static bool initialized; 273 static LogLockingState lock_log_file; 274}; 275 276// static 277bool LoggingLock::initialized = false; 278// static 279LockImpl* LoggingLock::log_lock = NULL; 280// static 281LogLockingState LoggingLock::lock_log_file = LOCK_LOG_FILE; 282 283#if defined(OS_WIN) 284// static 285MutexHandle LoggingLock::log_mutex = NULL; 286#elif defined(OS_POSIX) 287pthread_mutex_t LoggingLock::log_mutex = PTHREAD_MUTEX_INITIALIZER; 288#endif 289 290// Called by logging functions to ensure that debug_file is initialized 291// and can be used for writing. Returns false if the file could not be 292// initialized. debug_file will be NULL in this case. 293bool InitializeLogFileHandle() { 294 if (log_file) 295 return true; 296 297 if (!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 log_file_name = new PathString(); 301 GetDefaultLogFile(*log_file_name); 302 } 303 304 if (logging_destination == LOG_ONLY_TO_FILE || 305 logging_destination == LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) { 306#if defined(OS_WIN) 307 log_file = CreateFile(log_file_name->c_str(), GENERIC_WRITE, 308 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 309 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 310 if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) { 311 // try the current directory 312 log_file = CreateFile(L".\\debug.log", GENERIC_WRITE, 313 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 314 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 315 if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) { 316 log_file = NULL; 317 return false; 318 } 319 } 320 SetFilePointer(log_file, 0, 0, FILE_END); 321#elif defined(OS_POSIX) 322 log_file = fopen(log_file_name->c_str(), "a"); 323 if (log_file == NULL) 324 return false; 325#endif 326 } 327 328 return true; 329} 330 331void BaseInitLoggingImpl(const PathChar* new_log_file, 332 LoggingDestination logging_dest, 333 LogLockingState lock_log, 334 OldFileDeletionState delete_old) { 335 CommandLine* command_line = CommandLine::ForCurrentProcess(); 336 g_enable_dcheck = 337 command_line->HasSwitch(switches::kEnableDCHECK); 338 delete g_vlog_info; 339 g_vlog_info = NULL; 340 // Don't bother initializing g_vlog_info unless we use one of the 341 // vlog switches. 342 if (command_line->HasSwitch(switches::kV) || 343 command_line->HasSwitch(switches::kVModule)) { 344 g_vlog_info = 345 new VlogInfo(command_line->GetSwitchValueASCII(switches::kV), 346 command_line->GetSwitchValueASCII(switches::kVModule)); 347 } 348 349<<<<<<< HEAD 350void InitLogging(const PathChar* new_log_file, LoggingDestination logging_dest, 351 LogLockingState lock_log, OldFileDeletionState delete_old) { 352 g_enable_dcheck = 353#ifdef ANDROID 354 false; 355#else 356 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableDCHECK); 357#endif // ANDROID 358======= 359 LoggingLock::Init(lock_log, new_log_file); 360 361 LoggingLock logging_lock; 362>>>>>>> Chromium at release 7.0.540.0 363 364 if (log_file) { 365 // calling InitLogging twice or after some log call has already opened the 366 // default log file will re-initialize to the new options 367 CloseFile(log_file); 368 log_file = NULL; 369 } 370 371 logging_destination = logging_dest; 372 373 // ignore file options if logging is disabled or only to system 374 if (logging_destination == LOG_NONE || 375 logging_destination == LOG_ONLY_TO_SYSTEM_DEBUG_LOG) 376 return; 377 378 if (!log_file_name) 379 log_file_name = new PathString(); 380 *log_file_name = new_log_file; 381 if (delete_old == DELETE_OLD_LOG_FILE) 382 DeleteFilePath(*log_file_name); 383 384 InitializeLogFileHandle(); 385 386} 387 388void SetMinLogLevel(int level) { 389 min_log_level = level; 390} 391 392int GetMinLogLevel() { 393 return min_log_level; 394} 395 396int GetVlogLevelHelper(const char* file, size_t N) { 397 DCHECK_GT(N, 0U); 398 return g_vlog_info ? 399 g_vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) : 400 VlogInfo::kDefaultVlogLevel; 401} 402 403void SetLogFilterPrefix(const char* filter) { 404 if (log_filter_prefix) { 405 delete log_filter_prefix; 406 log_filter_prefix = NULL; 407 } 408 409 if (filter) 410 log_filter_prefix = new std::string(filter); 411} 412 413void SetLogItems(bool enable_process_id, bool enable_thread_id, 414 bool enable_timestamp, bool enable_tickcount) { 415 log_process_id = enable_process_id; 416 log_thread_id = enable_thread_id; 417 log_timestamp = enable_timestamp; 418 log_tickcount = enable_tickcount; 419} 420 421void SetShowErrorDialogs(bool enable_dialogs) { 422 show_error_dialogs = enable_dialogs; 423} 424 425void SetLogAssertHandler(LogAssertHandlerFunction handler) { 426 log_assert_handler = handler; 427} 428 429void SetLogReportHandler(LogReportHandlerFunction handler) { 430 log_report_handler = handler; 431} 432 433void SetLogMessageHandler(LogMessageHandlerFunction handler) { 434 log_message_handler = handler; 435} 436 437 438// Displays a message box to the user with the error message in it. 439// Used for fatal messages, where we close the app simultaneously. 440void DisplayDebugMessageInDialog(const std::string& str) { 441 if (str.empty()) 442 return; 443 444 if (!show_error_dialogs) 445 return; 446 447#if defined(OS_WIN) 448 // For Windows programs, it's possible that the message loop is 449 // messed up on a fatal error, and creating a MessageBox will cause 450 // that message loop to be run. Instead, we try to spawn another 451 // process that displays its command line. We look for "Debug 452 // Message.exe" in the same directory as the application. If it 453 // exists, we use it, otherwise, we use a regular message box. 454 wchar_t prog_name[MAX_PATH]; 455 GetModuleFileNameW(NULL, prog_name, MAX_PATH); 456 wchar_t* backslash = wcsrchr(prog_name, '\\'); 457 if (backslash) 458 backslash[1] = 0; 459 wcscat_s(prog_name, MAX_PATH, L"debug_message.exe"); 460 461 std::wstring cmdline = UTF8ToWide(str); 462 if (cmdline.empty()) 463 return; 464 465 STARTUPINFO startup_info; 466 memset(&startup_info, 0, sizeof(startup_info)); 467 startup_info.cb = sizeof(startup_info); 468 469 PROCESS_INFORMATION process_info; 470 if (CreateProcessW(prog_name, &cmdline[0], NULL, NULL, false, 0, NULL, 471 NULL, &startup_info, &process_info)) { 472 WaitForSingleObject(process_info.hProcess, INFINITE); 473 CloseHandle(process_info.hThread); 474 CloseHandle(process_info.hProcess); 475 } else { 476 // debug process broken, let's just do a message box 477 MessageBoxW(NULL, &cmdline[0], L"Fatal error", 478 MB_OK | MB_ICONHAND | MB_TOPMOST); 479 } 480#elif defined(USE_X11) && !defined(OS_CHROMEOS) 481 // Shell out to xmessage, which behaves like debug_message.exe, but is 482 // way more retro. We could use zenity/kdialog but then we're starting 483 // to get into needing to check the desktop env and this dialog should 484 // only be coming up in Very Bad situations. 485 std::vector<std::string> argv; 486 argv.push_back("xmessage"); 487 argv.push_back(str); 488 base::LaunchApp(argv, base::file_handle_mapping_vector(), true /* wait */, 489 NULL); 490#else 491 // http://code.google.com/p/chromium/issues/detail?id=37026 492 NOTIMPLEMENTED(); 493#endif 494} 495 496#if defined(OS_WIN) 497LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) { 498} 499 500LogMessage::SaveLastError::~SaveLastError() { 501 ::SetLastError(last_error_); 502} 503#endif // defined(OS_WIN) 504 505LogMessage::LogMessage(const char* file, int line, LogSeverity severity, 506 int ctr) 507 : severity_(severity) { 508 Init(file, line); 509} 510 511LogMessage::LogMessage(const char* file, int line, const CheckOpString& result) 512 : severity_(LOG_FATAL) { 513 Init(file, line); 514 stream_ << "Check failed: " << (*result.str_); 515} 516 517LogMessage::LogMessage(const char* file, int line, LogSeverity severity, 518 const CheckOpString& result) 519 : severity_(severity) { 520 Init(file, line); 521 stream_ << "Check failed: " << (*result.str_); 522} 523 524LogMessage::LogMessage(const char* file, int line) 525 : severity_(LOG_INFO) { 526 Init(file, line); 527} 528 529LogMessage::LogMessage(const char* file, int line, LogSeverity severity) 530 : severity_(severity) { 531 Init(file, line); 532} 533 534// writes the common header info to the stream 535void LogMessage::Init(const char* file, int line) { 536 // log only the filename 537 const char* last_slash = strrchr(file, '\\'); 538 if (last_slash) 539 file = last_slash + 1; 540 541 // TODO(darin): It might be nice if the columns were fixed width. 542 543 stream_ << '['; 544 if (log_process_id) 545 stream_ << CurrentProcessId() << ':'; 546 if (log_thread_id) 547 stream_ << CurrentThreadId() << ':'; 548 if (log_timestamp) { 549 time_t t = time(NULL); 550 struct tm local_time = {0}; 551#if _MSC_VER >= 1400 552 localtime_s(&local_time, &t); 553#else 554 localtime_r(&t, &local_time); 555#endif 556 struct tm* tm_time = &local_time; 557 stream_ << std::setfill('0') 558 << std::setw(2) << 1 + tm_time->tm_mon 559 << std::setw(2) << tm_time->tm_mday 560 << '/' 561 << std::setw(2) << tm_time->tm_hour 562 << std::setw(2) << tm_time->tm_min 563 << std::setw(2) << tm_time->tm_sec 564 << ':'; 565 } 566 if (log_tickcount) 567 stream_ << TickCount() << ':'; 568 stream_ << log_severity_names[severity_] << ":" << file << 569 "(" << line << ")] "; 570 571 message_start_ = stream_.tellp(); 572} 573 574LogMessage::~LogMessage() { 575 // TODO(brettw) modify the macros so that nothing is executed when the log 576 // level is too high. 577 if (severity_ < min_log_level) 578 return; 579 580#ifndef NDEBUG 581 if (severity_ == LOG_FATAL) { 582 // Include a stack trace on a fatal. 583 StackTrace trace; 584 stream_ << std::endl; // Newline to separate from log message. 585 trace.OutputToStream(&stream_); 586 } 587#endif 588 stream_ << std::endl; 589 std::string str_newline(stream_.str()); 590 591 // Give any log message handler first dibs on the message. 592 if (log_message_handler && log_message_handler(severity_, str_newline)) 593 return; 594 595 if (log_filter_prefix && severity_ <= kMaxFilteredLogLevel && 596 str_newline.compare(message_start_, log_filter_prefix->size(), 597 log_filter_prefix->data()) != 0) { 598 return; 599 } 600 601 if (logging_destination == LOG_ONLY_TO_SYSTEM_DEBUG_LOG || 602 logging_destination == LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) { 603#if defined(OS_WIN) 604 OutputDebugStringA(str_newline.c_str()); 605#endif 606 fprintf(stderr, "%s", str_newline.c_str()); 607 fflush(stderr); 608 } else if (severity_ >= kAlwaysPrintErrorLevel) { 609 // When we're only outputting to a log file, above a certain log level, we 610 // should still output to stderr so that we can better detect and diagnose 611 // problems with unit tests, especially on the buildbots. 612 fprintf(stderr, "%s", str_newline.c_str()); 613 fflush(stderr); 614 } 615 616 // We can have multiple threads and/or processes, so try to prevent them 617 // from clobbering each other's writes. 618 // If the client app did not call InitLogging, and the lock has not 619 // been created do it now. We do this on demand, but if two threads try 620 // to do this at the same time, there will be a race condition to create 621 // the lock. This is why InitLogging should be called from the main 622 // thread at the beginning of execution. 623 LoggingLock::Init(LOCK_LOG_FILE, NULL); 624 // write to log file 625 if (logging_destination != LOG_NONE && 626 logging_destination != LOG_ONLY_TO_SYSTEM_DEBUG_LOG) { 627 LoggingLock logging_lock; 628 if (InitializeLogFileHandle()) { 629#if defined(OS_WIN) 630 SetFilePointer(log_file, 0, 0, SEEK_END); 631 DWORD num_written; 632 WriteFile(log_file, 633 static_cast<const void*>(str_newline.c_str()), 634 static_cast<DWORD>(str_newline.length()), 635 &num_written, 636 NULL); 637#else 638 fprintf(log_file, "%s", str_newline.c_str()); 639 fflush(log_file); 640#endif 641 } 642 } 643 644 if (severity_ == LOG_FATAL) { 645 // display a message or break into the debugger on a fatal error 646 if (DebugUtil::BeingDebugged()) { 647 DebugUtil::BreakDebugger(); 648 } else { 649 if (log_assert_handler) { 650 // make a copy of the string for the handler out of paranoia 651 log_assert_handler(std::string(stream_.str())); 652 } else { 653 // Don't use the string with the newline, get a fresh version to send to 654 // the debug message process. We also don't display assertions to the 655 // user in release mode. The enduser can't do anything with this 656 // information, and displaying message boxes when the application is 657 // hosed can cause additional problems. 658#ifndef NDEBUG 659 DisplayDebugMessageInDialog(stream_.str()); 660#endif 661 // Crash the process to generate a dump. 662 DebugUtil::BreakDebugger(); 663 } 664 } 665 } else if (severity_ == LOG_ERROR_REPORT) { 666 // We are here only if the user runs with --enable-dcheck in release mode. 667 if (log_report_handler) { 668 log_report_handler(std::string(stream_.str())); 669 } else { 670 DisplayDebugMessageInDialog(stream_.str()); 671 } 672 } 673} 674 675#if defined(OS_WIN) 676// This has already been defined in the header, but defining it again as DWORD 677// ensures that the type used in the header is equivalent to DWORD. If not, 678// the redefinition is a compile error. 679typedef DWORD SystemErrorCode; 680#endif 681 682SystemErrorCode GetLastSystemErrorCode() { 683#if defined(OS_WIN) 684 return ::GetLastError(); 685#elif defined(OS_POSIX) 686 return errno; 687#else 688#error Not implemented 689#endif 690} 691 692#if defined(OS_WIN) 693Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, 694 int line, 695 LogSeverity severity, 696 SystemErrorCode err, 697 const char* module) 698 : err_(err), 699 module_(module), 700 log_message_(file, line, severity) { 701} 702 703Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, 704 int line, 705 LogSeverity severity, 706 SystemErrorCode err) 707 : err_(err), 708 module_(NULL), 709 log_message_(file, line, severity) { 710} 711 712Win32ErrorLogMessage::~Win32ErrorLogMessage() { 713 const int error_message_buffer_size = 256; 714 char msgbuf[error_message_buffer_size]; 715 DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM; 716 HMODULE hmod; 717 if (module_) { 718 hmod = GetModuleHandleA(module_); 719 if (hmod) { 720 flags |= FORMAT_MESSAGE_FROM_HMODULE; 721 } else { 722 // This makes a nested Win32ErrorLogMessage. It will have module_ of NULL 723 // so it will not call GetModuleHandle, so recursive errors are 724 // impossible. 725 DPLOG(WARNING) << "Couldn't open module " << module_ 726 << " for error message query"; 727 } 728 } else { 729 hmod = NULL; 730 } 731 DWORD len = FormatMessageA(flags, 732 hmod, 733 err_, 734 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 735 msgbuf, 736 sizeof(msgbuf) / sizeof(msgbuf[0]), 737 NULL); 738 if (len) { 739 while ((len > 0) && 740 isspace(static_cast<unsigned char>(msgbuf[len - 1]))) { 741 msgbuf[--len] = 0; 742 } 743 stream() << ": " << msgbuf; 744 } else { 745 stream() << ": Error " << GetLastError() << " while retrieving error " 746 << err_; 747 } 748} 749#elif defined(OS_POSIX) 750ErrnoLogMessage::ErrnoLogMessage(const char* file, 751 int line, 752 LogSeverity severity, 753 SystemErrorCode err) 754 : err_(err), 755 log_message_(file, line, severity) { 756} 757 758ErrnoLogMessage::~ErrnoLogMessage() { 759 stream() << ": " << safe_strerror(err_); 760} 761#endif // OS_WIN 762 763void CloseLogFile() { 764 LoggingLock logging_lock; 765 766 if (!log_file) 767 return; 768 769 CloseFile(log_file); 770 log_file = NULL; 771} 772 773void RawLog(int level, const char* message) { 774 if (level >= min_log_level) { 775 size_t bytes_written = 0; 776 const size_t message_len = strlen(message); 777 int rv; 778 while (bytes_written < message_len) { 779 rv = HANDLE_EINTR( 780 write(STDERR_FILENO, message + bytes_written, 781 message_len - bytes_written)); 782 if (rv < 0) { 783 // Give up, nothing we can do now. 784 break; 785 } 786 bytes_written += rv; 787 } 788 789 if (message_len > 0 && message[message_len - 1] != '\n') { 790 do { 791 rv = HANDLE_EINTR(write(STDERR_FILENO, "\n", 1)); 792 if (rv < 0) { 793 // Give up, nothing we can do now. 794 break; 795 } 796 } while (rv != 1); 797 } 798 } 799 800 if (level == LOG_FATAL) 801 DebugUtil::BreakDebugger(); 802} 803 804} // namespace logging 805 806std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) { 807 return out << WideToUTF8(std::wstring(wstr)); 808} 809