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