Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/logging.h" | 5 #include "base/logging.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <io.h> | 8 #include <io.h> |
| 9 #include <windows.h> | 9 #include <windows.h> |
| 10 typedef HANDLE FileHandle; | 10 typedef HANDLE FileHandle; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 | 73 |
| 74 void set_dcheck_state(DcheckState state) { | 74 void set_dcheck_state(DcheckState state) { |
| 75 g_dcheck_state = state; | 75 g_dcheck_state = state; |
| 76 } | 76 } |
| 77 | 77 |
| 78 namespace { | 78 namespace { |
| 79 | 79 |
| 80 VlogInfo* g_vlog_info = NULL; | 80 VlogInfo* g_vlog_info = NULL; |
| 81 VlogInfo* g_vlog_info_prev = NULL; | 81 VlogInfo* g_vlog_info_prev = NULL; |
| 82 | 82 |
| 83 const char* const log_severity_names[LOG_NUM_SEVERITIES] = { | 83 const char* const kLogSeverityNames[LOG_NUM_SEVERITIES] = { |
| 84 "INFO", "WARNING", "ERROR", "ERROR_REPORT", "FATAL" }; | 84 "INFO", "WARNING", "ERROR", "ERROR_REPORT", "FATAL" }; |
| 85 | 85 |
| 86 int min_log_level = 0; | 86 int g_min_log_level = 0; |
|
brettw
2013/06/19 18:10:13
This stuff is in an anonymous namespace in a .cc f
akalin
2013/06/19 19:59:18
Done. There were already some existing g_ variable
| |
| 87 | 87 |
| 88 // The default set here for logging_destination will only be used if | 88 LoggingDestination g_logging_destination = LOG_DEFAULT; |
| 89 // InitLogging is not called. On Windows, use a file next to the exe; | |
| 90 // on POSIX platforms, where it may not even be possible to locate the | |
| 91 // executable on disk, use stderr. | |
| 92 #if defined(OS_WIN) | |
| 93 LoggingDestination logging_destination = LOG_ONLY_TO_FILE; | |
| 94 #elif defined(OS_POSIX) | |
| 95 LoggingDestination logging_destination = LOG_ONLY_TO_SYSTEM_DEBUG_LOG; | |
| 96 #endif | |
| 97 | 89 |
| 98 // For LOG_ERROR and above, always print to stderr. | 90 // For LOG_ERROR and above, always print to stderr. |
| 99 const int kAlwaysPrintErrorLevel = LOG_ERROR; | 91 const int kAlwaysPrintErrorLevel = LOG_ERROR; |
| 100 | 92 |
| 101 // Which log file to use? This is initialized by InitLogging or | 93 // Which log file to use? This is initialized by InitLogging or |
| 102 // will be lazily initialized to the default value when it is | 94 // will be lazily initialized to the default value when it is |
| 103 // first needed. | 95 // first needed. |
| 104 #if defined(OS_WIN) | 96 #if defined(OS_WIN) |
| 105 typedef std::wstring PathString; | 97 typedef std::wstring PathString; |
| 106 #else | 98 #else |
| 107 typedef std::string PathString; | 99 typedef std::string PathString; |
| 108 #endif | 100 #endif |
| 109 PathString* log_file_name = NULL; | 101 PathString* g_log_file_name = NULL; |
| 110 | 102 |
| 111 // this file is lazily opened and the handle may be NULL | 103 // this file is lazily opened and the handle may be NULL |
| 112 FileHandle log_file = NULL; | 104 FileHandle g_log_file = NULL; |
| 113 | 105 |
| 114 // what should be prepended to each message? | 106 // what should be prepended to each message? |
| 115 bool log_process_id = false; | 107 bool g_log_process_id = false; |
| 116 bool log_thread_id = false; | 108 bool g_log_thread_id = false; |
| 117 bool log_timestamp = true; | 109 bool g_log_timestamp = true; |
| 118 bool log_tickcount = false; | 110 bool g_log_tickcount = false; |
| 119 | 111 |
| 120 // Should we pop up fatal debug messages in a dialog? | 112 // Should we pop up fatal debug messages in a dialog? |
| 121 bool show_error_dialogs = false; | 113 bool g_show_error_dialogs = false; |
| 122 | 114 |
| 123 // An assert handler override specified by the client to be called instead of | 115 // An assert handler override specified by the client to be called instead of |
| 124 // the debug message dialog and process termination. | 116 // the debug message dialog and process termination. |
| 125 LogAssertHandlerFunction log_assert_handler = NULL; | 117 LogAssertHandlerFunction g_log_assert_handler = NULL; |
| 126 // An report handler override specified by the client to be called instead of | 118 // An report handler override specified by the client to be called instead of |
| 127 // the debug message dialog. | 119 // the debug message dialog. |
| 128 LogReportHandlerFunction log_report_handler = NULL; | 120 LogReportHandlerFunction g_log_report_handler = NULL; |
| 129 // A log message handler that gets notified of every log message we process. | 121 // A log message handler that gets notified of every log message we process. |
| 130 LogMessageHandlerFunction log_message_handler = NULL; | 122 LogMessageHandlerFunction g_log_message_handler = NULL; |
| 131 | 123 |
| 132 // Helper functions to wrap platform differences. | 124 // Helper functions to wrap platform differences. |
| 133 | 125 |
| 134 int32 CurrentProcessId() { | 126 int32 CurrentProcessId() { |
| 135 #if defined(OS_WIN) | 127 #if defined(OS_WIN) |
| 136 return GetCurrentProcessId(); | 128 return GetCurrentProcessId(); |
| 137 #elif defined(OS_POSIX) | 129 #elif defined(OS_POSIX) |
| 138 return getpid(); | 130 return getpid(); |
| 139 #endif | 131 #endif |
| 140 } | 132 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 unlink(log_name.c_str()); | 169 unlink(log_name.c_str()); |
| 178 #endif | 170 #endif |
| 179 } | 171 } |
| 180 | 172 |
| 181 PathString GetDefaultLogFile() { | 173 PathString GetDefaultLogFile() { |
| 182 #if defined(OS_WIN) | 174 #if defined(OS_WIN) |
| 183 // On Windows we use the same path as the exe. | 175 // On Windows we use the same path as the exe. |
| 184 wchar_t module_name[MAX_PATH]; | 176 wchar_t module_name[MAX_PATH]; |
| 185 GetModuleFileName(NULL, module_name, MAX_PATH); | 177 GetModuleFileName(NULL, module_name, MAX_PATH); |
| 186 | 178 |
| 187 PathString log_file = module_name; | 179 PathString g_log_file = module_name; |
| 188 PathString::size_type last_backslash = | 180 PathString::size_type last_backslash = |
| 189 log_file.rfind('\\', log_file.size()); | 181 g_log_file.rfind('\\', g_log_file.size()); |
| 190 if (last_backslash != PathString::npos) | 182 if (last_backslash != PathString::npos) |
| 191 log_file.erase(last_backslash + 1); | 183 g_log_file.erase(last_backslash + 1); |
| 192 log_file += L"debug.log"; | 184 g_log_file += L"debug.log"; |
| 193 return log_file; | 185 return g_log_file; |
| 194 #elif defined(OS_POSIX) | 186 #elif defined(OS_POSIX) |
| 195 // On other platforms we just use the current directory. | 187 // On other platforms we just use the current directory. |
| 196 return PathString("debug.log"); | 188 return PathString("debug.log"); |
| 197 #endif | 189 #endif |
| 198 } | 190 } |
| 199 | 191 |
| 200 // This class acts as a wrapper for locking the logging files. | 192 // This class acts as a wrapper for locking the logging files. |
| 201 // LoggingLock::Init() should be called from the main thread before any logging | 193 // LoggingLock::Init() should be called from the main thread before any logging |
| 202 // is done. Then whenever logging, be sure to have a local LoggingLock | 194 // is done. Then whenever logging, be sure to have a local LoggingLock |
| 203 // instance on the stack. This will ensure that the lock is unlocked upon | 195 // instance on the stack. This will ensure that the lock is unlocked upon |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 307 // static | 299 // static |
| 308 MutexHandle LoggingLock::log_mutex = NULL; | 300 MutexHandle LoggingLock::log_mutex = NULL; |
| 309 #elif defined(OS_POSIX) | 301 #elif defined(OS_POSIX) |
| 310 pthread_mutex_t LoggingLock::log_mutex = PTHREAD_MUTEX_INITIALIZER; | 302 pthread_mutex_t LoggingLock::log_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 311 #endif | 303 #endif |
| 312 | 304 |
| 313 // Called by logging functions to ensure that debug_file is initialized | 305 // Called by logging functions to ensure that debug_file is initialized |
| 314 // and can be used for writing. Returns false if the file could not be | 306 // and can be used for writing. Returns false if the file could not be |
| 315 // initialized. debug_file will be NULL in this case. | 307 // initialized. debug_file will be NULL in this case. |
| 316 bool InitializeLogFileHandle() { | 308 bool InitializeLogFileHandle() { |
| 317 if (log_file) | 309 if (g_log_file) |
| 318 return true; | 310 return true; |
| 319 | 311 |
| 320 if (!log_file_name) { | 312 if (!g_log_file_name) { |
| 321 // Nobody has called InitLogging to specify a debug log file, so here we | 313 // Nobody has called InitLogging to specify a debug log file, so here we |
| 322 // initialize the log file name to a default. | 314 // initialize the log file name to a default. |
| 323 log_file_name = new PathString(GetDefaultLogFile()); | 315 g_log_file_name = new PathString(GetDefaultLogFile()); |
| 324 } | 316 } |
| 325 | 317 |
| 326 if (logging_destination == LOG_ONLY_TO_FILE || | 318 if ((g_logging_destination & LOG_TO_FILE) != 0) { |
| 327 logging_destination == LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) { | |
| 328 #if defined(OS_WIN) | 319 #if defined(OS_WIN) |
| 329 log_file = CreateFile(log_file_name->c_str(), GENERIC_WRITE, | 320 g_log_file = CreateFile(g_log_file_name->c_str(), GENERIC_WRITE, |
| 330 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | |
| 331 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 332 if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) { | |
| 333 // try the current directory | |
| 334 log_file = CreateFile(L".\\debug.log", GENERIC_WRITE, | |
| 335 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | 321 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, |
| 336 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | 322 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| 337 if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) { | 323 if (g_log_file == INVALID_HANDLE_VALUE || g_log_file == NULL) { |
| 338 log_file = NULL; | 324 // try the current directory |
| 325 g_log_file = CreateFile(L".\\debug.log", GENERIC_WRITE, | |
| 326 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | |
| 327 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 328 if (g_log_file == INVALID_HANDLE_VALUE || g_log_file == NULL) { | |
| 329 g_log_file = NULL; | |
| 339 return false; | 330 return false; |
| 340 } | 331 } |
| 341 } | 332 } |
| 342 SetFilePointer(log_file, 0, 0, FILE_END); | 333 SetFilePointer(g_log_file, 0, 0, FILE_END); |
| 343 #elif defined(OS_POSIX) | 334 #elif defined(OS_POSIX) |
| 344 log_file = fopen(log_file_name->c_str(), "a"); | 335 g_log_file = fopen(g_log_file_name->c_str(), "a"); |
| 345 if (log_file == NULL) | 336 if (g_log_file == NULL) |
| 346 return false; | 337 return false; |
| 347 #endif | 338 #endif |
| 348 } | 339 } |
| 349 | 340 |
| 350 return true; | 341 return true; |
| 351 } | 342 } |
| 352 | 343 |
| 353 } // namespace | 344 } // namespace |
| 354 | 345 |
| 346 LoggingSettings::LoggingSettings() | |
| 347 : logging_dest(LOG_DEFAULT), | |
| 348 log_file(NULL), | |
| 349 lock_log(LOCK_LOG_FILE), | |
| 350 delete_old(APPEND_TO_OLD_LOG_FILE), | |
| 351 dcheck_state(DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS) {} | |
| 355 | 352 |
| 356 bool BaseInitLoggingImpl(const PathChar* new_log_file, | 353 bool BaseInitLoggingImpl(const LoggingSettings& settings) { |
| 357 LoggingDestination logging_dest, | |
| 358 LogLockingState lock_log, | |
| 359 OldFileDeletionState delete_old, | |
| 360 DcheckState dcheck_state) { | |
| 361 #if defined(OS_NACL) | 354 #if defined(OS_NACL) |
| 362 CHECK(logging_dest == LOG_NONE || | 355 // Can log only to the system debug log. |
| 363 logging_dest == LOG_ONLY_TO_SYSTEM_DEBUG_LOG); | 356 CHECK_EQ(settings.logging_dest & ~LOG_TO_SYSTEM_DEBUG_LOG, 0); |
| 364 #endif | 357 #endif |
| 365 g_dcheck_state = dcheck_state; | 358 g_dcheck_state = settings.dcheck_state; |
| 366 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 359 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 367 // Don't bother initializing g_vlog_info unless we use one of the | 360 // Don't bother initializing g_vlog_info unless we use one of the |
| 368 // vlog switches. | 361 // vlog switches. |
| 369 if (command_line->HasSwitch(switches::kV) || | 362 if (command_line->HasSwitch(switches::kV) || |
| 370 command_line->HasSwitch(switches::kVModule)) { | 363 command_line->HasSwitch(switches::kVModule)) { |
| 371 // NOTE: If g_vlog_info has already been initialized, it might be in use | 364 // NOTE: If g_vlog_info has already been initialized, it might be in use |
| 372 // by another thread. Don't delete the old VLogInfo, just create a second | 365 // by another thread. Don't delete the old VLogInfo, just create a second |
| 373 // one. We keep track of both to avoid memory leak warnings. | 366 // one. We keep track of both to avoid memory leak warnings. |
| 374 CHECK(!g_vlog_info_prev); | 367 CHECK(!g_vlog_info_prev); |
| 375 g_vlog_info_prev = g_vlog_info; | 368 g_vlog_info_prev = g_vlog_info; |
| 376 | 369 |
| 377 g_vlog_info = | 370 g_vlog_info = |
| 378 new VlogInfo(command_line->GetSwitchValueASCII(switches::kV), | 371 new VlogInfo(command_line->GetSwitchValueASCII(switches::kV), |
| 379 command_line->GetSwitchValueASCII(switches::kVModule), | 372 command_line->GetSwitchValueASCII(switches::kVModule), |
| 380 &min_log_level); | 373 &g_min_log_level); |
| 381 } | 374 } |
| 382 | 375 |
| 383 LoggingLock::Init(lock_log, new_log_file); | 376 LoggingLock::Init(settings.lock_log, settings.log_file); |
| 384 | 377 |
| 385 LoggingLock logging_lock; | 378 LoggingLock logging_lock; |
| 386 | 379 |
| 387 if (log_file) { | 380 if (g_log_file) { |
| 388 // calling InitLogging twice or after some log call has already opened the | 381 // calling InitLogging twice or after some log call has already opened the |
| 389 // default log file will re-initialize to the new options | 382 // default log file will re-initialize to the new options |
| 390 CloseFile(log_file); | 383 CloseFile(g_log_file); |
| 391 log_file = NULL; | 384 g_log_file = NULL; |
| 392 } | 385 } |
| 393 | 386 |
| 394 logging_destination = logging_dest; | 387 g_logging_destination = settings.logging_dest; |
| 395 | 388 |
| 396 // ignore file options if logging is disabled or only to system | 389 // ignore file options unless logging to file is set. |
| 397 if (logging_destination == LOG_NONE || | 390 if ((g_logging_destination & LOG_TO_FILE) == 0) |
| 398 logging_destination == LOG_ONLY_TO_SYSTEM_DEBUG_LOG) | |
| 399 return true; | 391 return true; |
| 400 | 392 |
| 401 if (!log_file_name) | 393 if (!g_log_file_name) |
| 402 log_file_name = new PathString(); | 394 g_log_file_name = new PathString(); |
| 403 *log_file_name = new_log_file; | 395 *g_log_file_name = settings.log_file; |
| 404 if (delete_old == DELETE_OLD_LOG_FILE) | 396 if (settings.delete_old == DELETE_OLD_LOG_FILE) |
| 405 DeleteFilePath(*log_file_name); | 397 DeleteFilePath(*g_log_file_name); |
| 406 | 398 |
| 407 return InitializeLogFileHandle(); | 399 return InitializeLogFileHandle(); |
| 408 } | 400 } |
| 409 | 401 |
| 410 void SetMinLogLevel(int level) { | 402 void SetMinLogLevel(int level) { |
| 411 min_log_level = std::min(LOG_ERROR_REPORT, level); | 403 g_min_log_level = std::min(LOG_ERROR_REPORT, level); |
| 412 } | 404 } |
| 413 | 405 |
| 414 int GetMinLogLevel() { | 406 int GetMinLogLevel() { |
| 415 return min_log_level; | 407 return g_min_log_level; |
| 416 } | 408 } |
| 417 | 409 |
| 418 int GetVlogVerbosity() { | 410 int GetVlogVerbosity() { |
| 419 return std::max(-1, LOG_INFO - GetMinLogLevel()); | 411 return std::max(-1, LOG_INFO - GetMinLogLevel()); |
| 420 } | 412 } |
| 421 | 413 |
| 422 int GetVlogLevelHelper(const char* file, size_t N) { | 414 int GetVlogLevelHelper(const char* file, size_t N) { |
| 423 DCHECK_GT(N, 0U); | 415 DCHECK_GT(N, 0U); |
| 424 // Note: g_vlog_info may change on a different thread during startup | 416 // Note: g_vlog_info may change on a different thread during startup |
| 425 // (but will always be valid or NULL). | 417 // (but will always be valid or NULL). |
| 426 VlogInfo* vlog_info = g_vlog_info; | 418 VlogInfo* vlog_info = g_vlog_info; |
| 427 return vlog_info ? | 419 return vlog_info ? |
| 428 vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) : | 420 vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) : |
| 429 GetVlogVerbosity(); | 421 GetVlogVerbosity(); |
| 430 } | 422 } |
| 431 | 423 |
| 432 void SetLogItems(bool enable_process_id, bool enable_thread_id, | 424 void SetLogItems(bool enable_process_id, bool enable_thread_id, |
| 433 bool enable_timestamp, bool enable_tickcount) { | 425 bool enable_timestamp, bool enable_tickcount) { |
| 434 log_process_id = enable_process_id; | 426 g_log_process_id = enable_process_id; |
| 435 log_thread_id = enable_thread_id; | 427 g_log_thread_id = enable_thread_id; |
| 436 log_timestamp = enable_timestamp; | 428 g_log_timestamp = enable_timestamp; |
| 437 log_tickcount = enable_tickcount; | 429 g_log_tickcount = enable_tickcount; |
| 438 } | 430 } |
| 439 | 431 |
| 440 void SetShowErrorDialogs(bool enable_dialogs) { | 432 void SetShowErrorDialogs(bool enable_dialogs) { |
| 441 show_error_dialogs = enable_dialogs; | 433 g_show_error_dialogs = enable_dialogs; |
| 442 } | 434 } |
| 443 | 435 |
| 444 void SetLogAssertHandler(LogAssertHandlerFunction handler) { | 436 void SetLogAssertHandler(LogAssertHandlerFunction handler) { |
| 445 log_assert_handler = handler; | 437 g_log_assert_handler = handler; |
| 446 } | 438 } |
| 447 | 439 |
| 448 void SetLogReportHandler(LogReportHandlerFunction handler) { | 440 void SetLogReportHandler(LogReportHandlerFunction handler) { |
| 449 log_report_handler = handler; | 441 g_log_report_handler = handler; |
| 450 } | 442 } |
| 451 | 443 |
| 452 void SetLogMessageHandler(LogMessageHandlerFunction handler) { | 444 void SetLogMessageHandler(LogMessageHandlerFunction handler) { |
| 453 log_message_handler = handler; | 445 g_log_message_handler = handler; |
| 454 } | 446 } |
| 455 | 447 |
| 456 LogMessageHandlerFunction GetLogMessageHandler() { | 448 LogMessageHandlerFunction GetLogMessageHandler() { |
| 457 return log_message_handler; | 449 return g_log_message_handler; |
| 458 } | 450 } |
| 459 | 451 |
| 460 // MSVC doesn't like complex extern templates and DLLs. | 452 // MSVC doesn't like complex extern templates and DLLs. |
| 461 #if !defined(COMPILER_MSVC) | 453 #if !defined(COMPILER_MSVC) |
| 462 // Explicit instantiations for commonly used comparisons. | 454 // Explicit instantiations for commonly used comparisons. |
| 463 template std::string* MakeCheckOpString<int, int>( | 455 template std::string* MakeCheckOpString<int, int>( |
| 464 const int&, const int&, const char* names); | 456 const int&, const int&, const char* names); |
| 465 template std::string* MakeCheckOpString<unsigned long, unsigned long>( | 457 template std::string* MakeCheckOpString<unsigned long, unsigned long>( |
| 466 const unsigned long&, const unsigned long&, const char* names); | 458 const unsigned long&, const unsigned long&, const char* names); |
| 467 template std::string* MakeCheckOpString<unsigned long, unsigned int>( | 459 template std::string* MakeCheckOpString<unsigned long, unsigned int>( |
| 468 const unsigned long&, const unsigned int&, const char* names); | 460 const unsigned long&, const unsigned int&, const char* names); |
| 469 template std::string* MakeCheckOpString<unsigned int, unsigned long>( | 461 template std::string* MakeCheckOpString<unsigned int, unsigned long>( |
| 470 const unsigned int&, const unsigned long&, const char* names); | 462 const unsigned int&, const unsigned long&, const char* names); |
| 471 template std::string* MakeCheckOpString<std::string, std::string>( | 463 template std::string* MakeCheckOpString<std::string, std::string>( |
| 472 const std::string&, const std::string&, const char* name); | 464 const std::string&, const std::string&, const char* name); |
| 473 #endif | 465 #endif |
| 474 | 466 |
| 475 // Displays a message box to the user with the error message in it. | 467 // Displays a message box to the user with the error message in it. |
| 476 // Used for fatal messages, where we close the app simultaneously. | 468 // Used for fatal messages, where we close the app simultaneously. |
| 477 // This is for developers only; we don't use this in circumstances | 469 // This is for developers only; we don't use this in circumstances |
| 478 // (like release builds) where users could see it, since users don't | 470 // (like release builds) where users could see it, since users don't |
| 479 // understand these messages anyway. | 471 // understand these messages anyway. |
| 480 void DisplayDebugMessageInDialog(const std::string& str) { | 472 void DisplayDebugMessageInDialog(const std::string& str) { |
| 481 if (str.empty()) | 473 if (str.empty()) |
| 482 return; | 474 return; |
| 483 | 475 |
| 484 if (!show_error_dialogs) | 476 if (!g_show_error_dialogs) |
| 485 return; | 477 return; |
| 486 | 478 |
| 487 #if defined(OS_WIN) | 479 #if defined(OS_WIN) |
| 488 // For Windows programs, it's possible that the message loop is | 480 // For Windows programs, it's possible that the message loop is |
| 489 // messed up on a fatal error, and creating a MessageBox will cause | 481 // messed up on a fatal error, and creating a MessageBox will cause |
| 490 // that message loop to be run. Instead, we try to spawn another | 482 // that message loop to be run. Instead, we try to spawn another |
| 491 // process that displays its command line. We look for "Debug | 483 // process that displays its command line. We look for "Debug |
| 492 // Message.exe" in the same directory as the application. If it | 484 // Message.exe" in the same directory as the application. If it |
| 493 // exists, we use it, otherwise, we use a regular message box. | 485 // exists, we use it, otherwise, we use a regular message box. |
| 494 wchar_t prog_name[MAX_PATH]; | 486 wchar_t prog_name[MAX_PATH]; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 // Include a stack trace on a fatal. | 563 // Include a stack trace on a fatal. |
| 572 base::debug::StackTrace trace; | 564 base::debug::StackTrace trace; |
| 573 stream_ << std::endl; // Newline to separate from log message. | 565 stream_ << std::endl; // Newline to separate from log message. |
| 574 trace.OutputToStream(&stream_); | 566 trace.OutputToStream(&stream_); |
| 575 } | 567 } |
| 576 #endif | 568 #endif |
| 577 stream_ << std::endl; | 569 stream_ << std::endl; |
| 578 std::string str_newline(stream_.str()); | 570 std::string str_newline(stream_.str()); |
| 579 | 571 |
| 580 // Give any log message handler first dibs on the message. | 572 // Give any log message handler first dibs on the message. |
| 581 if (log_message_handler && log_message_handler(severity_, file_, line_, | 573 if (g_log_message_handler && |
| 582 message_start_, str_newline)) { | 574 g_log_message_handler(severity_, file_, line_, |
| 575 message_start_, str_newline)) { | |
| 583 // The handler took care of it, no further processing. | 576 // The handler took care of it, no further processing. |
| 584 return; | 577 return; |
| 585 } | 578 } |
| 586 | 579 |
| 587 if (logging_destination == LOG_ONLY_TO_SYSTEM_DEBUG_LOG || | 580 if ((g_logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) != 0) { |
| 588 logging_destination == LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) { | |
| 589 #if defined(OS_WIN) | 581 #if defined(OS_WIN) |
| 590 OutputDebugStringA(str_newline.c_str()); | 582 OutputDebugStringA(str_newline.c_str()); |
| 591 #elif defined(OS_ANDROID) | 583 #elif defined(OS_ANDROID) |
| 592 android_LogPriority priority = | 584 android_LogPriority priority = |
| 593 (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN; | 585 (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN; |
| 594 switch (severity_) { | 586 switch (severity_) { |
| 595 case LOG_INFO: | 587 case LOG_INFO: |
| 596 priority = ANDROID_LOG_INFO; | 588 priority = ANDROID_LOG_INFO; |
| 597 break; | 589 break; |
| 598 case LOG_WARNING: | 590 case LOG_WARNING: |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 620 | 612 |
| 621 // We can have multiple threads and/or processes, so try to prevent them | 613 // We can have multiple threads and/or processes, so try to prevent them |
| 622 // from clobbering each other's writes. | 614 // from clobbering each other's writes. |
| 623 // If the client app did not call InitLogging, and the lock has not | 615 // If the client app did not call InitLogging, and the lock has not |
| 624 // been created do it now. We do this on demand, but if two threads try | 616 // been created do it now. We do this on demand, but if two threads try |
| 625 // to do this at the same time, there will be a race condition to create | 617 // to do this at the same time, there will be a race condition to create |
| 626 // the lock. This is why InitLogging should be called from the main | 618 // the lock. This is why InitLogging should be called from the main |
| 627 // thread at the beginning of execution. | 619 // thread at the beginning of execution. |
| 628 LoggingLock::Init(LOCK_LOG_FILE, NULL); | 620 LoggingLock::Init(LOCK_LOG_FILE, NULL); |
| 629 // write to log file | 621 // write to log file |
| 630 if (logging_destination != LOG_NONE && | 622 if ((g_logging_destination & LOG_TO_FILE) != 0) { |
| 631 logging_destination != LOG_ONLY_TO_SYSTEM_DEBUG_LOG) { | |
| 632 LoggingLock logging_lock; | 623 LoggingLock logging_lock; |
| 633 if (InitializeLogFileHandle()) { | 624 if (InitializeLogFileHandle()) { |
| 634 #if defined(OS_WIN) | 625 #if defined(OS_WIN) |
| 635 SetFilePointer(log_file, 0, 0, SEEK_END); | 626 SetFilePointer(g_log_file, 0, 0, SEEK_END); |
| 636 DWORD num_written; | 627 DWORD num_written; |
| 637 WriteFile(log_file, | 628 WriteFile(g_log_file, |
| 638 static_cast<const void*>(str_newline.c_str()), | 629 static_cast<const void*>(str_newline.c_str()), |
| 639 static_cast<DWORD>(str_newline.length()), | 630 static_cast<DWORD>(str_newline.length()), |
| 640 &num_written, | 631 &num_written, |
| 641 NULL); | 632 NULL); |
| 642 #else | 633 #else |
| 643 fprintf(log_file, "%s", str_newline.c_str()); | 634 fprintf(g_log_file, "%s", str_newline.c_str()); |
| 644 fflush(log_file); | 635 fflush(g_log_file); |
| 645 #endif | 636 #endif |
| 646 } | 637 } |
| 647 } | 638 } |
| 648 | 639 |
| 649 if (severity_ == LOG_FATAL) { | 640 if (severity_ == LOG_FATAL) { |
| 650 // Ensure the first characters of the string are on the stack so they | 641 // Ensure the first characters of the string are on the stack so they |
| 651 // are contained in minidumps for diagnostic purposes. | 642 // are contained in minidumps for diagnostic purposes. |
| 652 char str_stack[1024]; | 643 char str_stack[1024]; |
| 653 str_newline.copy(str_stack, arraysize(str_stack)); | 644 str_newline.copy(str_stack, arraysize(str_stack)); |
| 654 base::debug::Alias(str_stack); | 645 base::debug::Alias(str_stack); |
| 655 | 646 |
| 656 // display a message or break into the debugger on a fatal error | 647 // display a message or break into the debugger on a fatal error |
| 657 if (base::debug::BeingDebugged()) { | 648 if (base::debug::BeingDebugged()) { |
| 658 base::debug::BreakDebugger(); | 649 base::debug::BreakDebugger(); |
| 659 } else { | 650 } else { |
| 660 if (log_assert_handler) { | 651 if (g_log_assert_handler) { |
| 661 // make a copy of the string for the handler out of paranoia | 652 // make a copy of the string for the handler out of paranoia |
| 662 log_assert_handler(std::string(stream_.str())); | 653 g_log_assert_handler(std::string(stream_.str())); |
| 663 } else { | 654 } else { |
| 664 // Don't use the string with the newline, get a fresh version to send to | 655 // Don't use the string with the newline, get a fresh version to send to |
| 665 // the debug message process. We also don't display assertions to the | 656 // the debug message process. We also don't display assertions to the |
| 666 // user in release mode. The enduser can't do anything with this | 657 // user in release mode. The enduser can't do anything with this |
| 667 // information, and displaying message boxes when the application is | 658 // information, and displaying message boxes when the application is |
| 668 // hosed can cause additional problems. | 659 // hosed can cause additional problems. |
| 669 #ifndef NDEBUG | 660 #ifndef NDEBUG |
| 670 DisplayDebugMessageInDialog(stream_.str()); | 661 DisplayDebugMessageInDialog(stream_.str()); |
| 671 #endif | 662 #endif |
| 672 // Crash the process to generate a dump. | 663 // Crash the process to generate a dump. |
| 673 base::debug::BreakDebugger(); | 664 base::debug::BreakDebugger(); |
| 674 } | 665 } |
| 675 } | 666 } |
| 676 } else if (severity_ == LOG_ERROR_REPORT) { | 667 } else if (severity_ == LOG_ERROR_REPORT) { |
| 677 // We are here only if the user runs with --enable-dcheck in release mode. | 668 // We are here only if the user runs with --enable-dcheck in release mode. |
| 678 if (log_report_handler) { | 669 if (g_log_report_handler) { |
| 679 log_report_handler(std::string(stream_.str())); | 670 g_log_report_handler(std::string(stream_.str())); |
| 680 } else { | 671 } else { |
| 681 DisplayDebugMessageInDialog(stream_.str()); | 672 DisplayDebugMessageInDialog(stream_.str()); |
| 682 } | 673 } |
| 683 } | 674 } |
| 684 } | 675 } |
| 685 | 676 |
| 686 // writes the common header info to the stream | 677 // writes the common header info to the stream |
| 687 void LogMessage::Init(const char* file, int line) { | 678 void LogMessage::Init(const char* file, int line) { |
| 688 base::StringPiece filename(file); | 679 base::StringPiece filename(file); |
| 689 size_t last_slash_pos = filename.find_last_of("\\/"); | 680 size_t last_slash_pos = filename.find_last_of("\\/"); |
| 690 if (last_slash_pos != base::StringPiece::npos) | 681 if (last_slash_pos != base::StringPiece::npos) |
| 691 filename.remove_prefix(last_slash_pos + 1); | 682 filename.remove_prefix(last_slash_pos + 1); |
| 692 | 683 |
| 693 // TODO(darin): It might be nice if the columns were fixed width. | 684 // TODO(darin): It might be nice if the columns were fixed width. |
| 694 | 685 |
| 695 stream_ << '['; | 686 stream_ << '['; |
| 696 if (log_process_id) | 687 if (g_log_process_id) |
| 697 stream_ << CurrentProcessId() << ':'; | 688 stream_ << CurrentProcessId() << ':'; |
| 698 if (log_thread_id) | 689 if (g_log_thread_id) |
| 699 stream_ << base::PlatformThread::CurrentId() << ':'; | 690 stream_ << base::PlatformThread::CurrentId() << ':'; |
| 700 if (log_timestamp) { | 691 if (g_log_timestamp) { |
| 701 time_t t = time(NULL); | 692 time_t t = time(NULL); |
| 702 struct tm local_time = {0}; | 693 struct tm local_time = {0}; |
| 703 #if _MSC_VER >= 1400 | 694 #if _MSC_VER >= 1400 |
| 704 localtime_s(&local_time, &t); | 695 localtime_s(&local_time, &t); |
| 705 #else | 696 #else |
| 706 localtime_r(&t, &local_time); | 697 localtime_r(&t, &local_time); |
| 707 #endif | 698 #endif |
| 708 struct tm* tm_time = &local_time; | 699 struct tm* tm_time = &local_time; |
| 709 stream_ << std::setfill('0') | 700 stream_ << std::setfill('0') |
| 710 << std::setw(2) << 1 + tm_time->tm_mon | 701 << std::setw(2) << 1 + tm_time->tm_mon |
| 711 << std::setw(2) << tm_time->tm_mday | 702 << std::setw(2) << tm_time->tm_mday |
| 712 << '/' | 703 << '/' |
| 713 << std::setw(2) << tm_time->tm_hour | 704 << std::setw(2) << tm_time->tm_hour |
| 714 << std::setw(2) << tm_time->tm_min | 705 << std::setw(2) << tm_time->tm_min |
| 715 << std::setw(2) << tm_time->tm_sec | 706 << std::setw(2) << tm_time->tm_sec |
| 716 << ':'; | 707 << ':'; |
| 717 } | 708 } |
| 718 if (log_tickcount) | 709 if (g_log_tickcount) |
| 719 stream_ << TickCount() << ':'; | 710 stream_ << TickCount() << ':'; |
| 720 if (severity_ >= 0) | 711 if (severity_ >= 0) |
| 721 stream_ << log_severity_names[severity_]; | 712 stream_ << kLogSeverityNames[severity_]; |
| 722 else | 713 else |
| 723 stream_ << "VERBOSE" << -severity_; | 714 stream_ << "VERBOSE" << -severity_; |
| 724 | 715 |
| 725 stream_ << ":" << filename << "(" << line << ")] "; | 716 stream_ << ":" << filename << "(" << line << ")] "; |
| 726 | 717 |
| 727 message_start_ = stream_.tellp(); | 718 message_start_ = stream_.tellp(); |
| 728 } | 719 } |
| 729 | 720 |
| 730 #if defined(OS_WIN) | 721 #if defined(OS_WIN) |
| 731 // This has already been defined in the header, but defining it again as DWORD | 722 // This has already been defined in the header, but defining it again as DWORD |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 815 } | 806 } |
| 816 | 807 |
| 817 ErrnoLogMessage::~ErrnoLogMessage() { | 808 ErrnoLogMessage::~ErrnoLogMessage() { |
| 818 stream() << ": " << safe_strerror(err_); | 809 stream() << ": " << safe_strerror(err_); |
| 819 } | 810 } |
| 820 #endif // OS_WIN | 811 #endif // OS_WIN |
| 821 | 812 |
| 822 void CloseLogFile() { | 813 void CloseLogFile() { |
| 823 LoggingLock logging_lock; | 814 LoggingLock logging_lock; |
| 824 | 815 |
| 825 if (!log_file) | 816 if (!g_log_file) |
| 826 return; | 817 return; |
| 827 | 818 |
| 828 CloseFile(log_file); | 819 CloseFile(g_log_file); |
| 829 log_file = NULL; | 820 g_log_file = NULL; |
| 830 } | 821 } |
| 831 | 822 |
| 832 void RawLog(int level, const char* message) { | 823 void RawLog(int level, const char* message) { |
| 833 if (level >= min_log_level) { | 824 if (level >= g_min_log_level) { |
| 834 size_t bytes_written = 0; | 825 size_t bytes_written = 0; |
| 835 const size_t message_len = strlen(message); | 826 const size_t message_len = strlen(message); |
| 836 int rv; | 827 int rv; |
| 837 while (bytes_written < message_len) { | 828 while (bytes_written < message_len) { |
| 838 rv = HANDLE_EINTR( | 829 rv = HANDLE_EINTR( |
| 839 write(STDERR_FILENO, message + bytes_written, | 830 write(STDERR_FILENO, message + bytes_written, |
| 840 message_len - bytes_written)); | 831 message_len - bytes_written)); |
| 841 if (rv < 0) { | 832 if (rv < 0) { |
| 842 // Give up, nothing we can do now. | 833 // Give up, nothing we can do now. |
| 843 break; | 834 break; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 858 | 849 |
| 859 if (level == LOG_FATAL) | 850 if (level == LOG_FATAL) |
| 860 base::debug::BreakDebugger(); | 851 base::debug::BreakDebugger(); |
| 861 } | 852 } |
| 862 | 853 |
| 863 // This was defined at the beginning of this file. | 854 // This was defined at the beginning of this file. |
| 864 #undef write | 855 #undef write |
| 865 | 856 |
| 866 #if defined(OS_WIN) | 857 #if defined(OS_WIN) |
| 867 std::wstring GetLogFileFullPath() { | 858 std::wstring GetLogFileFullPath() { |
| 868 if (log_file_name) | 859 if (g_log_file_name) |
| 869 return *log_file_name; | 860 return *g_log_file_name; |
| 870 return std::wstring(); | 861 return std::wstring(); |
| 871 } | 862 } |
| 872 #endif | 863 #endif |
| 873 | 864 |
| 874 } // namespace logging | 865 } // namespace logging |
| 875 | 866 |
| 876 std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) { | 867 std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) { |
| 877 return out << WideToUTF8(std::wstring(wstr)); | 868 return out << WideToUTF8(std::wstring(wstr)); |
| 878 } | 869 } |
| OLD | NEW |