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