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