1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/chromium/base/logging.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,866 @@ 1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/logging.h" 1.9 + 1.10 +#if defined(OS_WIN) 1.11 +#include <io.h> 1.12 +#include <windows.h> 1.13 +typedef HANDLE FileHandle; 1.14 +typedef HANDLE MutexHandle; 1.15 +// Windows warns on using write(). It prefers _write(). 1.16 +#define write(fd, buf, count) _write(fd, buf, static_cast<unsigned int>(count)) 1.17 +// Windows doesn't define STDERR_FILENO. Define it here. 1.18 +#define STDERR_FILENO 2 1.19 +#elif defined(OS_MACOSX) 1.20 +#include <mach/mach.h> 1.21 +#include <mach/mach_time.h> 1.22 +#include <mach-o/dyld.h> 1.23 +#elif defined(OS_POSIX) 1.24 +#if defined(OS_NACL) 1.25 +#include <sys/time.h> // timespec doesn't seem to be in <time.h> 1.26 +#else 1.27 +#include <sys/syscall.h> 1.28 +#endif 1.29 +#include <time.h> 1.30 +#endif 1.31 + 1.32 +#if defined(OS_POSIX) 1.33 +#include <errno.h> 1.34 +#include <pthread.h> 1.35 +#include <stdio.h> 1.36 +#include <stdlib.h> 1.37 +#include <string.h> 1.38 +#include <unistd.h> 1.39 +#define MAX_PATH PATH_MAX 1.40 +typedef FILE* FileHandle; 1.41 +typedef pthread_mutex_t* MutexHandle; 1.42 +#endif 1.43 + 1.44 +#include <algorithm> 1.45 +#include <cstring> 1.46 +#include <ctime> 1.47 +#include <iomanip> 1.48 +#include <ostream> 1.49 + 1.50 +#include "base/base_switches.h" 1.51 +#include "base/command_line.h" 1.52 +#include "base/debug/alias.h" 1.53 +#include "base/debug/debugger.h" 1.54 +#include "base/debug/stack_trace.h" 1.55 +#include "base/posix/eintr_wrapper.h" 1.56 +#include "base/strings/string_piece.h" 1.57 +#include "base/strings/utf_string_conversions.h" 1.58 +#include "base/synchronization/lock_impl.h" 1.59 +#include "base/threading/platform_thread.h" 1.60 +#include "base/vlog.h" 1.61 +#if defined(OS_POSIX) 1.62 +#include "base/safe_strerror_posix.h" 1.63 +#endif 1.64 + 1.65 +#if defined(OS_ANDROID) 1.66 +#include <android/log.h> 1.67 +#endif 1.68 + 1.69 +namespace logging { 1.70 + 1.71 +DcheckState g_dcheck_state = DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS; 1.72 + 1.73 +DcheckState get_dcheck_state() { 1.74 + return g_dcheck_state; 1.75 +} 1.76 + 1.77 +void set_dcheck_state(DcheckState state) { 1.78 + g_dcheck_state = state; 1.79 +} 1.80 + 1.81 +namespace { 1.82 + 1.83 +VlogInfo* g_vlog_info = NULL; 1.84 +VlogInfo* g_vlog_info_prev = NULL; 1.85 + 1.86 +const char* const log_severity_names[LOG_NUM_SEVERITIES] = { 1.87 + "INFO", "WARNING", "ERROR", "ERROR_REPORT", "FATAL" }; 1.88 + 1.89 +int min_log_level = 0; 1.90 + 1.91 +LoggingDestination logging_destination = LOG_DEFAULT; 1.92 + 1.93 +// For LOG_ERROR and above, always print to stderr. 1.94 +const int kAlwaysPrintErrorLevel = LOG_ERROR; 1.95 + 1.96 +// Which log file to use? This is initialized by InitLogging or 1.97 +// will be lazily initialized to the default value when it is 1.98 +// first needed. 1.99 +#if defined(OS_WIN) 1.100 +typedef std::wstring PathString; 1.101 +#else 1.102 +typedef std::string PathString; 1.103 +#endif 1.104 +PathString* log_file_name = NULL; 1.105 + 1.106 +// this file is lazily opened and the handle may be NULL 1.107 +FileHandle log_file = NULL; 1.108 + 1.109 +// what should be prepended to each message? 1.110 +bool log_process_id = false; 1.111 +bool log_thread_id = false; 1.112 +bool log_timestamp = true; 1.113 +bool log_tickcount = false; 1.114 + 1.115 +// Should we pop up fatal debug messages in a dialog? 1.116 +bool show_error_dialogs = false; 1.117 + 1.118 +// An assert handler override specified by the client to be called instead of 1.119 +// the debug message dialog and process termination. 1.120 +LogAssertHandlerFunction log_assert_handler = NULL; 1.121 +// An report handler override specified by the client to be called instead of 1.122 +// the debug message dialog. 1.123 +LogReportHandlerFunction log_report_handler = NULL; 1.124 +// A log message handler that gets notified of every log message we process. 1.125 +LogMessageHandlerFunction log_message_handler = NULL; 1.126 + 1.127 +// Helper functions to wrap platform differences. 1.128 + 1.129 +int32 CurrentProcessId() { 1.130 +#if defined(OS_WIN) 1.131 + return GetCurrentProcessId(); 1.132 +#elif defined(OS_POSIX) 1.133 + return getpid(); 1.134 +#endif 1.135 +} 1.136 + 1.137 +uint64 TickCount() { 1.138 +#if defined(OS_WIN) 1.139 + return GetTickCount(); 1.140 +#elif defined(OS_MACOSX) 1.141 + return mach_absolute_time(); 1.142 +#elif defined(OS_NACL) 1.143 + // NaCl sadly does not have _POSIX_TIMERS enabled in sys/features.h 1.144 + // So we have to use clock() for now. 1.145 + return clock(); 1.146 +#elif defined(OS_POSIX) 1.147 + struct timespec ts; 1.148 + clock_gettime(CLOCK_MONOTONIC, &ts); 1.149 + 1.150 + uint64 absolute_micro = 1.151 + static_cast<int64>(ts.tv_sec) * 1000000 + 1.152 + static_cast<int64>(ts.tv_nsec) / 1000; 1.153 + 1.154 + return absolute_micro; 1.155 +#endif 1.156 +} 1.157 + 1.158 +void DeleteFilePath(const PathString& log_name) { 1.159 +#if defined(OS_WIN) 1.160 + DeleteFile(log_name.c_str()); 1.161 +#elif defined (OS_NACL) 1.162 + // Do nothing; unlink() isn't supported on NaCl. 1.163 +#else 1.164 + unlink(log_name.c_str()); 1.165 +#endif 1.166 +} 1.167 + 1.168 +PathString GetDefaultLogFile() { 1.169 +#if defined(OS_WIN) 1.170 + // On Windows we use the same path as the exe. 1.171 + wchar_t module_name[MAX_PATH]; 1.172 + GetModuleFileName(NULL, module_name, MAX_PATH); 1.173 + 1.174 + PathString log_file = module_name; 1.175 + PathString::size_type last_backslash = 1.176 + log_file.rfind('\\', log_file.size()); 1.177 + if (last_backslash != PathString::npos) 1.178 + log_file.erase(last_backslash + 1); 1.179 + log_file += L"debug.log"; 1.180 + return log_file; 1.181 +#elif defined(OS_POSIX) 1.182 + // On other platforms we just use the current directory. 1.183 + return PathString("debug.log"); 1.184 +#endif 1.185 +} 1.186 + 1.187 +// This class acts as a wrapper for locking the logging files. 1.188 +// LoggingLock::Init() should be called from the main thread before any logging 1.189 +// is done. Then whenever logging, be sure to have a local LoggingLock 1.190 +// instance on the stack. This will ensure that the lock is unlocked upon 1.191 +// exiting the frame. 1.192 +// LoggingLocks can not be nested. 1.193 +class LoggingLock { 1.194 + public: 1.195 + LoggingLock() { 1.196 + LockLogging(); 1.197 + } 1.198 + 1.199 + ~LoggingLock() { 1.200 + UnlockLogging(); 1.201 + } 1.202 + 1.203 + static void Init(LogLockingState lock_log, const PathChar* new_log_file) { 1.204 + if (initialized) 1.205 + return; 1.206 + lock_log_file = lock_log; 1.207 + if (lock_log_file == LOCK_LOG_FILE) { 1.208 +#if defined(OS_WIN) 1.209 + if (!log_mutex) { 1.210 + std::wstring safe_name; 1.211 + if (new_log_file) 1.212 + safe_name = new_log_file; 1.213 + else 1.214 + safe_name = GetDefaultLogFile(); 1.215 + // \ is not a legal character in mutex names so we replace \ with / 1.216 + std::replace(safe_name.begin(), safe_name.end(), '\\', '/'); 1.217 + std::wstring t(L"Global\\"); 1.218 + t.append(safe_name); 1.219 + log_mutex = ::CreateMutex(NULL, FALSE, t.c_str()); 1.220 + 1.221 + if (log_mutex == NULL) { 1.222 +#if DEBUG 1.223 + // Keep the error code for debugging 1.224 + int error = GetLastError(); // NOLINT 1.225 + base::debug::BreakDebugger(); 1.226 +#endif 1.227 + // Return nicely without putting initialized to true. 1.228 + return; 1.229 + } 1.230 + } 1.231 +#endif 1.232 + } else { 1.233 + log_lock = new base::internal::LockImpl(); 1.234 + } 1.235 + initialized = true; 1.236 + } 1.237 + 1.238 + private: 1.239 + static void LockLogging() { 1.240 + if (lock_log_file == LOCK_LOG_FILE) { 1.241 +#if defined(OS_WIN) 1.242 + ::WaitForSingleObject(log_mutex, INFINITE); 1.243 + // WaitForSingleObject could have returned WAIT_ABANDONED. We don't 1.244 + // abort the process here. UI tests might be crashy sometimes, 1.245 + // and aborting the test binary only makes the problem worse. 1.246 + // We also don't use LOG macros because that might lead to an infinite 1.247 + // loop. For more info see http://crbug.com/18028. 1.248 +#elif defined(OS_POSIX) 1.249 + pthread_mutex_lock(&log_mutex); 1.250 +#endif 1.251 + } else { 1.252 + // use the lock 1.253 + log_lock->Lock(); 1.254 + } 1.255 + } 1.256 + 1.257 + static void UnlockLogging() { 1.258 + if (lock_log_file == LOCK_LOG_FILE) { 1.259 +#if defined(OS_WIN) 1.260 + ReleaseMutex(log_mutex); 1.261 +#elif defined(OS_POSIX) 1.262 + pthread_mutex_unlock(&log_mutex); 1.263 +#endif 1.264 + } else { 1.265 + log_lock->Unlock(); 1.266 + } 1.267 + } 1.268 + 1.269 + // The lock is used if log file locking is false. It helps us avoid problems 1.270 + // with multiple threads writing to the log file at the same time. Use 1.271 + // LockImpl directly instead of using Lock, because Lock makes logging calls. 1.272 + static base::internal::LockImpl* log_lock; 1.273 + 1.274 + // When we don't use a lock, we are using a global mutex. We need to do this 1.275 + // because LockFileEx is not thread safe. 1.276 +#if defined(OS_WIN) 1.277 + static MutexHandle log_mutex; 1.278 +#elif defined(OS_POSIX) 1.279 + static pthread_mutex_t log_mutex; 1.280 +#endif 1.281 + 1.282 + static bool initialized; 1.283 + static LogLockingState lock_log_file; 1.284 +}; 1.285 + 1.286 +// static 1.287 +bool LoggingLock::initialized = false; 1.288 +// static 1.289 +base::internal::LockImpl* LoggingLock::log_lock = NULL; 1.290 +// static 1.291 +LogLockingState LoggingLock::lock_log_file = LOCK_LOG_FILE; 1.292 + 1.293 +#if defined(OS_WIN) 1.294 +// static 1.295 +MutexHandle LoggingLock::log_mutex = NULL; 1.296 +#elif defined(OS_POSIX) 1.297 +pthread_mutex_t LoggingLock::log_mutex = PTHREAD_MUTEX_INITIALIZER; 1.298 +#endif 1.299 + 1.300 +// Called by logging functions to ensure that debug_file is initialized 1.301 +// and can be used for writing. Returns false if the file could not be 1.302 +// initialized. debug_file will be NULL in this case. 1.303 +bool InitializeLogFileHandle() { 1.304 + if (log_file) 1.305 + return true; 1.306 + 1.307 + if (!log_file_name) { 1.308 + // Nobody has called InitLogging to specify a debug log file, so here we 1.309 + // initialize the log file name to a default. 1.310 + log_file_name = new PathString(GetDefaultLogFile()); 1.311 + } 1.312 + 1.313 + if ((logging_destination & LOG_TO_FILE) != 0) { 1.314 +#if defined(OS_WIN) 1.315 + log_file = CreateFile(log_file_name->c_str(), GENERIC_WRITE, 1.316 + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 1.317 + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1.318 + if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) { 1.319 + // try the current directory 1.320 + log_file = CreateFile(L".\\debug.log", GENERIC_WRITE, 1.321 + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 1.322 + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1.323 + if (log_file == INVALID_HANDLE_VALUE || log_file == NULL) { 1.324 + log_file = NULL; 1.325 + return false; 1.326 + } 1.327 + } 1.328 + SetFilePointer(log_file, 0, 0, FILE_END); 1.329 +#elif defined(OS_POSIX) 1.330 + log_file = fopen(log_file_name->c_str(), "a"); 1.331 + if (log_file == NULL) 1.332 + return false; 1.333 +#endif 1.334 + } 1.335 + 1.336 + return true; 1.337 +} 1.338 + 1.339 +void CloseFile(FileHandle log) { 1.340 +#if defined(OS_WIN) 1.341 + CloseHandle(log); 1.342 +#else 1.343 + fclose(log); 1.344 +#endif 1.345 +} 1.346 + 1.347 +void CloseLogFileUnlocked() { 1.348 + if (!log_file) 1.349 + return; 1.350 + 1.351 + CloseFile(log_file); 1.352 + log_file = NULL; 1.353 +} 1.354 + 1.355 +} // namespace 1.356 + 1.357 +LoggingSettings::LoggingSettings() 1.358 + : logging_dest(LOG_DEFAULT), 1.359 + log_file(NULL), 1.360 + lock_log(LOCK_LOG_FILE), 1.361 + delete_old(APPEND_TO_OLD_LOG_FILE), 1.362 + dcheck_state(DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS) {} 1.363 + 1.364 +bool BaseInitLoggingImpl(const LoggingSettings& settings) { 1.365 +#if defined(OS_NACL) 1.366 + // Can log only to the system debug log. 1.367 + CHECK_EQ(settings.logging_dest & ~LOG_TO_SYSTEM_DEBUG_LOG, 0); 1.368 +#endif 1.369 + g_dcheck_state = settings.dcheck_state; 1.370 + CommandLine* command_line = CommandLine::ForCurrentProcess(); 1.371 + // Don't bother initializing g_vlog_info unless we use one of the 1.372 + // vlog switches. 1.373 + if (command_line->HasSwitch(switches::kV) || 1.374 + command_line->HasSwitch(switches::kVModule)) { 1.375 + // NOTE: If g_vlog_info has already been initialized, it might be in use 1.376 + // by another thread. Don't delete the old VLogInfo, just create a second 1.377 + // one. We keep track of both to avoid memory leak warnings. 1.378 + CHECK(!g_vlog_info_prev); 1.379 + g_vlog_info_prev = g_vlog_info; 1.380 + 1.381 + g_vlog_info = 1.382 + new VlogInfo(command_line->GetSwitchValueASCII(switches::kV), 1.383 + command_line->GetSwitchValueASCII(switches::kVModule), 1.384 + &min_log_level); 1.385 + } 1.386 + 1.387 + logging_destination = settings.logging_dest; 1.388 + 1.389 + // ignore file options unless logging to file is set. 1.390 + if ((logging_destination & LOG_TO_FILE) == 0) 1.391 + return true; 1.392 + 1.393 + LoggingLock::Init(settings.lock_log, settings.log_file); 1.394 + LoggingLock logging_lock; 1.395 + 1.396 + // Calling InitLogging twice or after some log call has already opened the 1.397 + // default log file will re-initialize to the new options. 1.398 + CloseLogFileUnlocked(); 1.399 + 1.400 + if (!log_file_name) 1.401 + log_file_name = new PathString(); 1.402 + *log_file_name = settings.log_file; 1.403 + if (settings.delete_old == DELETE_OLD_LOG_FILE) 1.404 + DeleteFilePath(*log_file_name); 1.405 + 1.406 + return InitializeLogFileHandle(); 1.407 +} 1.408 + 1.409 +void SetMinLogLevel(int level) { 1.410 + min_log_level = std::min(LOG_ERROR_REPORT, level); 1.411 +} 1.412 + 1.413 +int GetMinLogLevel() { 1.414 + return min_log_level; 1.415 +} 1.416 + 1.417 +int GetVlogVerbosity() { 1.418 + return std::max(-1, LOG_INFO - GetMinLogLevel()); 1.419 +} 1.420 + 1.421 +int GetVlogLevelHelper(const char* file, size_t N) { 1.422 + DCHECK_GT(N, 0U); 1.423 + // Note: g_vlog_info may change on a different thread during startup 1.424 + // (but will always be valid or NULL). 1.425 + VlogInfo* vlog_info = g_vlog_info; 1.426 + return vlog_info ? 1.427 + vlog_info->GetVlogLevel(base::StringPiece(file, N - 1)) : 1.428 + GetVlogVerbosity(); 1.429 +} 1.430 + 1.431 +void SetLogItems(bool enable_process_id, bool enable_thread_id, 1.432 + bool enable_timestamp, bool enable_tickcount) { 1.433 + log_process_id = enable_process_id; 1.434 + log_thread_id = enable_thread_id; 1.435 + log_timestamp = enable_timestamp; 1.436 + log_tickcount = enable_tickcount; 1.437 +} 1.438 + 1.439 +void SetShowErrorDialogs(bool enable_dialogs) { 1.440 + show_error_dialogs = enable_dialogs; 1.441 +} 1.442 + 1.443 +void SetLogAssertHandler(LogAssertHandlerFunction handler) { 1.444 + log_assert_handler = handler; 1.445 +} 1.446 + 1.447 +void SetLogReportHandler(LogReportHandlerFunction handler) { 1.448 + log_report_handler = handler; 1.449 +} 1.450 + 1.451 +void SetLogMessageHandler(LogMessageHandlerFunction handler) { 1.452 + log_message_handler = handler; 1.453 +} 1.454 + 1.455 +LogMessageHandlerFunction GetLogMessageHandler() { 1.456 + return log_message_handler; 1.457 +} 1.458 + 1.459 +// MSVC doesn't like complex extern templates and DLLs. 1.460 +#if !defined(COMPILER_MSVC) 1.461 +// Explicit instantiations for commonly used comparisons. 1.462 +template std::string* MakeCheckOpString<int, int>( 1.463 + const int&, const int&, const char* names); 1.464 +template std::string* MakeCheckOpString<unsigned long, unsigned long>( 1.465 + const unsigned long&, const unsigned long&, const char* names); 1.466 +template std::string* MakeCheckOpString<unsigned long, unsigned int>( 1.467 + const unsigned long&, const unsigned int&, const char* names); 1.468 +template std::string* MakeCheckOpString<unsigned int, unsigned long>( 1.469 + const unsigned int&, const unsigned long&, const char* names); 1.470 +template std::string* MakeCheckOpString<std::string, std::string>( 1.471 + const std::string&, const std::string&, const char* name); 1.472 +#endif 1.473 + 1.474 +// Displays a message box to the user with the error message in it. 1.475 +// Used for fatal messages, where we close the app simultaneously. 1.476 +// This is for developers only; we don't use this in circumstances 1.477 +// (like release builds) where users could see it, since users don't 1.478 +// understand these messages anyway. 1.479 +void DisplayDebugMessageInDialog(const std::string& str) { 1.480 + if (str.empty()) 1.481 + return; 1.482 + 1.483 + if (!show_error_dialogs) 1.484 + return; 1.485 + 1.486 +#if defined(OS_WIN) 1.487 + // For Windows programs, it's possible that the message loop is 1.488 + // messed up on a fatal error, and creating a MessageBox will cause 1.489 + // that message loop to be run. Instead, we try to spawn another 1.490 + // process that displays its command line. We look for "Debug 1.491 + // Message.exe" in the same directory as the application. If it 1.492 + // exists, we use it, otherwise, we use a regular message box. 1.493 + wchar_t prog_name[MAX_PATH]; 1.494 + GetModuleFileNameW(NULL, prog_name, MAX_PATH); 1.495 + wchar_t* backslash = wcsrchr(prog_name, '\\'); 1.496 + if (backslash) 1.497 + backslash[1] = 0; 1.498 + wcscat_s(prog_name, MAX_PATH, L"debug_message.exe"); 1.499 + 1.500 + std::wstring cmdline = UTF8ToWide(str); 1.501 + if (cmdline.empty()) 1.502 + return; 1.503 + 1.504 + STARTUPINFO startup_info; 1.505 + memset(&startup_info, 0, sizeof(startup_info)); 1.506 + startup_info.cb = sizeof(startup_info); 1.507 + 1.508 + PROCESS_INFORMATION process_info; 1.509 + if (CreateProcessW(prog_name, &cmdline[0], NULL, NULL, false, 0, NULL, 1.510 + NULL, &startup_info, &process_info)) { 1.511 + WaitForSingleObject(process_info.hProcess, INFINITE); 1.512 + CloseHandle(process_info.hThread); 1.513 + CloseHandle(process_info.hProcess); 1.514 + } else { 1.515 + // debug process broken, let's just do a message box 1.516 + MessageBoxW(NULL, &cmdline[0], L"Fatal error", 1.517 + MB_OK | MB_ICONHAND | MB_TOPMOST); 1.518 + } 1.519 +#else 1.520 + // We intentionally don't implement a dialog on other platforms. 1.521 + // You can just look at stderr. 1.522 +#endif 1.523 +} 1.524 + 1.525 +#if defined(OS_WIN) 1.526 +LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) { 1.527 +} 1.528 + 1.529 +LogMessage::SaveLastError::~SaveLastError() { 1.530 + ::SetLastError(last_error_); 1.531 +} 1.532 +#endif // defined(OS_WIN) 1.533 + 1.534 +LogMessage::LogMessage(const char* file, int line, LogSeverity severity, 1.535 + int ctr) 1.536 + : severity_(severity), file_(file), line_(line) { 1.537 + Init(file, line); 1.538 +} 1.539 + 1.540 +LogMessage::LogMessage(const char* file, int line) 1.541 + : severity_(LOG_INFO), file_(file), line_(line) { 1.542 + Init(file, line); 1.543 +} 1.544 + 1.545 +LogMessage::LogMessage(const char* file, int line, LogSeverity severity) 1.546 + : severity_(severity), file_(file), line_(line) { 1.547 + Init(file, line); 1.548 +} 1.549 + 1.550 +LogMessage::LogMessage(const char* file, int line, std::string* result) 1.551 + : severity_(LOG_FATAL), file_(file), line_(line) { 1.552 + Init(file, line); 1.553 + stream_ << "Check failed: " << *result; 1.554 + delete result; 1.555 +} 1.556 + 1.557 +LogMessage::LogMessage(const char* file, int line, LogSeverity severity, 1.558 + std::string* result) 1.559 + : severity_(severity), file_(file), line_(line) { 1.560 + Init(file, line); 1.561 + stream_ << "Check failed: " << *result; 1.562 + delete result; 1.563 +} 1.564 + 1.565 +LogMessage::~LogMessage() { 1.566 +#if !defined(NDEBUG) && !defined(OS_NACL) 1.567 + if (severity_ == LOG_FATAL) { 1.568 + // Include a stack trace on a fatal. 1.569 + base::debug::StackTrace trace; 1.570 + stream_ << std::endl; // Newline to separate from log message. 1.571 + trace.OutputToStream(&stream_); 1.572 + } 1.573 +#endif 1.574 + stream_ << std::endl; 1.575 + std::string str_newline(stream_.str()); 1.576 + 1.577 + // Give any log message handler first dibs on the message. 1.578 + if (log_message_handler && 1.579 + log_message_handler(severity_, file_, line_, 1.580 + message_start_, str_newline)) { 1.581 + // The handler took care of it, no further processing. 1.582 + return; 1.583 + } 1.584 + 1.585 + if ((logging_destination & LOG_TO_SYSTEM_DEBUG_LOG) != 0) { 1.586 +#if defined(OS_WIN) 1.587 + OutputDebugStringA(str_newline.c_str()); 1.588 +#elif defined(OS_ANDROID) 1.589 + android_LogPriority priority = 1.590 + (severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN; 1.591 + switch (severity_) { 1.592 + case LOG_INFO: 1.593 + priority = ANDROID_LOG_INFO; 1.594 + break; 1.595 + case LOG_WARNING: 1.596 + priority = ANDROID_LOG_WARN; 1.597 + break; 1.598 + case LOG_ERROR: 1.599 + case LOG_ERROR_REPORT: 1.600 + priority = ANDROID_LOG_ERROR; 1.601 + break; 1.602 + case LOG_FATAL: 1.603 + priority = ANDROID_LOG_FATAL; 1.604 + break; 1.605 + } 1.606 + __android_log_write(priority, "chromium", str_newline.c_str()); 1.607 +#endif 1.608 + fprintf(stderr, "%s", str_newline.c_str()); 1.609 + fflush(stderr); 1.610 + } else if (severity_ >= kAlwaysPrintErrorLevel) { 1.611 + // When we're only outputting to a log file, above a certain log level, we 1.612 + // should still output to stderr so that we can better detect and diagnose 1.613 + // problems with unit tests, especially on the buildbots. 1.614 + fprintf(stderr, "%s", str_newline.c_str()); 1.615 + fflush(stderr); 1.616 + } 1.617 + 1.618 + // write to log file 1.619 + if ((logging_destination & LOG_TO_FILE) != 0) { 1.620 + // We can have multiple threads and/or processes, so try to prevent them 1.621 + // from clobbering each other's writes. 1.622 + // If the client app did not call InitLogging, and the lock has not 1.623 + // been created do it now. We do this on demand, but if two threads try 1.624 + // to do this at the same time, there will be a race condition to create 1.625 + // the lock. This is why InitLogging should be called from the main 1.626 + // thread at the beginning of execution. 1.627 + LoggingLock::Init(LOCK_LOG_FILE, NULL); 1.628 + LoggingLock logging_lock; 1.629 + if (InitializeLogFileHandle()) { 1.630 +#if defined(OS_WIN) 1.631 + SetFilePointer(log_file, 0, 0, SEEK_END); 1.632 + DWORD num_written; 1.633 + WriteFile(log_file, 1.634 + static_cast<const void*>(str_newline.c_str()), 1.635 + static_cast<DWORD>(str_newline.length()), 1.636 + &num_written, 1.637 + NULL); 1.638 +#else 1.639 + fprintf(log_file, "%s", str_newline.c_str()); 1.640 + fflush(log_file); 1.641 +#endif 1.642 + } 1.643 + } 1.644 + 1.645 + if (severity_ == LOG_FATAL) { 1.646 + // Ensure the first characters of the string are on the stack so they 1.647 + // are contained in minidumps for diagnostic purposes. 1.648 + char str_stack[1024]; 1.649 + str_newline.copy(str_stack, arraysize(str_stack)); 1.650 + base::debug::Alias(str_stack); 1.651 + 1.652 + // display a message or break into the debugger on a fatal error 1.653 + if (base::debug::BeingDebugged()) { 1.654 + base::debug::BreakDebugger(); 1.655 + } else { 1.656 + if (log_assert_handler) { 1.657 + // make a copy of the string for the handler out of paranoia 1.658 + log_assert_handler(std::string(stream_.str())); 1.659 + } else { 1.660 + // Don't use the string with the newline, get a fresh version to send to 1.661 + // the debug message process. We also don't display assertions to the 1.662 + // user in release mode. The enduser can't do anything with this 1.663 + // information, and displaying message boxes when the application is 1.664 + // hosed can cause additional problems. 1.665 +#ifndef NDEBUG 1.666 + DisplayDebugMessageInDialog(stream_.str()); 1.667 +#endif 1.668 + // Crash the process to generate a dump. 1.669 + base::debug::BreakDebugger(); 1.670 + } 1.671 + } 1.672 + } else if (severity_ == LOG_ERROR_REPORT) { 1.673 + // We are here only if the user runs with --enable-dcheck in release mode. 1.674 + if (log_report_handler) { 1.675 + log_report_handler(std::string(stream_.str())); 1.676 + } else { 1.677 + DisplayDebugMessageInDialog(stream_.str()); 1.678 + } 1.679 + } 1.680 +} 1.681 + 1.682 +// writes the common header info to the stream 1.683 +void LogMessage::Init(const char* file, int line) { 1.684 + base::StringPiece filename(file); 1.685 + size_t last_slash_pos = filename.find_last_of("\\/"); 1.686 + if (last_slash_pos != base::StringPiece::npos) 1.687 + filename.remove_prefix(last_slash_pos + 1); 1.688 + 1.689 + // TODO(darin): It might be nice if the columns were fixed width. 1.690 + 1.691 + stream_ << '['; 1.692 + if (log_process_id) 1.693 + stream_ << CurrentProcessId() << ':'; 1.694 + if (log_thread_id) 1.695 + stream_ << base::PlatformThread::CurrentId() << ':'; 1.696 + if (log_timestamp) { 1.697 + time_t t = time(NULL); 1.698 + struct tm local_time = {0}; 1.699 +#if _MSC_VER >= 1400 1.700 + localtime_s(&local_time, &t); 1.701 +#else 1.702 + localtime_r(&t, &local_time); 1.703 +#endif 1.704 + struct tm* tm_time = &local_time; 1.705 + stream_ << std::setfill('0') 1.706 + << std::setw(2) << 1 + tm_time->tm_mon 1.707 + << std::setw(2) << tm_time->tm_mday 1.708 + << '/' 1.709 + << std::setw(2) << tm_time->tm_hour 1.710 + << std::setw(2) << tm_time->tm_min 1.711 + << std::setw(2) << tm_time->tm_sec 1.712 + << ':'; 1.713 + } 1.714 + if (log_tickcount) 1.715 + stream_ << TickCount() << ':'; 1.716 + if (severity_ >= 0) 1.717 + stream_ << log_severity_names[severity_]; 1.718 + else 1.719 + stream_ << "VERBOSE" << -severity_; 1.720 + 1.721 + stream_ << ":" << filename << "(" << line << ")] "; 1.722 + 1.723 + message_start_ = stream_.tellp(); 1.724 +} 1.725 + 1.726 +#if defined(OS_WIN) 1.727 +// This has already been defined in the header, but defining it again as DWORD 1.728 +// ensures that the type used in the header is equivalent to DWORD. If not, 1.729 +// the redefinition is a compile error. 1.730 +typedef DWORD SystemErrorCode; 1.731 +#endif 1.732 + 1.733 +SystemErrorCode GetLastSystemErrorCode() { 1.734 +#if defined(OS_WIN) 1.735 + return ::GetLastError(); 1.736 +#elif defined(OS_POSIX) 1.737 + return errno; 1.738 +#else 1.739 +#error Not implemented 1.740 +#endif 1.741 +} 1.742 + 1.743 +#if defined(OS_WIN) 1.744 +Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, 1.745 + int line, 1.746 + LogSeverity severity, 1.747 + SystemErrorCode err, 1.748 + const char* module) 1.749 + : err_(err), 1.750 + module_(module), 1.751 + log_message_(file, line, severity) { 1.752 +} 1.753 + 1.754 +Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, 1.755 + int line, 1.756 + LogSeverity severity, 1.757 + SystemErrorCode err) 1.758 + : err_(err), 1.759 + module_(NULL), 1.760 + log_message_(file, line, severity) { 1.761 +} 1.762 + 1.763 +Win32ErrorLogMessage::~Win32ErrorLogMessage() { 1.764 + const int error_message_buffer_size = 256; 1.765 + char msgbuf[error_message_buffer_size]; 1.766 + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; 1.767 + HMODULE hmod; 1.768 + if (module_) { 1.769 + hmod = GetModuleHandleA(module_); 1.770 + if (hmod) { 1.771 + flags |= FORMAT_MESSAGE_FROM_HMODULE; 1.772 + } else { 1.773 + // This makes a nested Win32ErrorLogMessage. It will have module_ of NULL 1.774 + // so it will not call GetModuleHandle, so recursive errors are 1.775 + // impossible. 1.776 + DPLOG(WARNING) << "Couldn't open module " << module_ 1.777 + << " for error message query"; 1.778 + } 1.779 + } else { 1.780 + hmod = NULL; 1.781 + } 1.782 + DWORD len = FormatMessageA(flags, 1.783 + hmod, 1.784 + err_, 1.785 + 0, 1.786 + msgbuf, 1.787 + sizeof(msgbuf) / sizeof(msgbuf[0]), 1.788 + NULL); 1.789 + if (len) { 1.790 + while ((len > 0) && 1.791 + isspace(static_cast<unsigned char>(msgbuf[len - 1]))) { 1.792 + msgbuf[--len] = 0; 1.793 + } 1.794 + stream() << ": " << msgbuf; 1.795 + } else { 1.796 + stream() << ": Error " << GetLastError() << " while retrieving error " 1.797 + << err_; 1.798 + } 1.799 + // We're about to crash (CHECK). Put |err_| on the stack (by placing it in a 1.800 + // field) and use Alias in hopes that it makes it into crash dumps. 1.801 + DWORD last_error = err_; 1.802 + base::debug::Alias(&last_error); 1.803 +} 1.804 +#elif defined(OS_POSIX) 1.805 +ErrnoLogMessage::ErrnoLogMessage(const char* file, 1.806 + int line, 1.807 + LogSeverity severity, 1.808 + SystemErrorCode err) 1.809 + : err_(err), 1.810 + log_message_(file, line, severity) { 1.811 +} 1.812 + 1.813 +ErrnoLogMessage::~ErrnoLogMessage() { 1.814 + stream() << ": " << safe_strerror(err_); 1.815 +} 1.816 +#endif // OS_WIN 1.817 + 1.818 +void CloseLogFile() { 1.819 + LoggingLock logging_lock; 1.820 + CloseLogFileUnlocked(); 1.821 +} 1.822 + 1.823 +void RawLog(int level, const char* message) { 1.824 + if (level >= min_log_level) { 1.825 + size_t bytes_written = 0; 1.826 + const size_t message_len = strlen(message); 1.827 + int rv; 1.828 + while (bytes_written < message_len) { 1.829 + rv = HANDLE_EINTR( 1.830 + write(STDERR_FILENO, message + bytes_written, 1.831 + message_len - bytes_written)); 1.832 + if (rv < 0) { 1.833 + // Give up, nothing we can do now. 1.834 + break; 1.835 + } 1.836 + bytes_written += rv; 1.837 + } 1.838 + 1.839 + if (message_len > 0 && message[message_len - 1] != '\n') { 1.840 + do { 1.841 + rv = HANDLE_EINTR(write(STDERR_FILENO, "\n", 1)); 1.842 + if (rv < 0) { 1.843 + // Give up, nothing we can do now. 1.844 + break; 1.845 + } 1.846 + } while (rv != 1); 1.847 + } 1.848 + } 1.849 + 1.850 + if (level == LOG_FATAL) 1.851 + base::debug::BreakDebugger(); 1.852 +} 1.853 + 1.854 +// This was defined at the beginning of this file. 1.855 +#undef write 1.856 + 1.857 +#if defined(OS_WIN) 1.858 +std::wstring GetLogFileFullPath() { 1.859 + if (log_file_name) 1.860 + return *log_file_name; 1.861 + return std::wstring(); 1.862 +} 1.863 +#endif 1.864 + 1.865 +} // namespace logging 1.866 + 1.867 +std::ostream& operator<<(std::ostream& out, const wchar_t* wstr) { 1.868 + return out << WideToUTF8(std::wstring(wstr)); 1.869 +}