diff options
Diffstat (limited to 'extern/glog/src/logging.cc')
-rw-r--r-- | extern/glog/src/logging.cc | 130 |
1 files changed, 108 insertions, 22 deletions
diff --git a/extern/glog/src/logging.cc b/extern/glog/src/logging.cc index 3e8f48e814d..0c86cf62296 100644 --- a/extern/glog/src/logging.cc +++ b/extern/glog/src/logging.cc @@ -114,11 +114,6 @@ GLOG_DEFINE_bool(drop_log_memory, true, "Drop in-memory buffers of log contents. "Logs can grow very quickly and they are rarely read before they " "need to be evicted from memory. Instead, drop them from memory " "as soon as they are flushed to disk."); -_START_GOOGLE_NAMESPACE_ -namespace logging { -static const int64 kPageSize = getpagesize(); -} -_END_GOOGLE_NAMESPACE_ #endif // By default, errors (including fatal errors) get logged to stderr as @@ -188,7 +183,7 @@ GLOG_DEFINE_string(log_backtrace_at, "", #ifndef HAVE_PREAD #if defined(OS_WINDOWS) -#include <BaseTsd.h> +#include <basetsd.h> #define ssize_t SSIZE_T #endif static ssize_t pread(int fd, void* buf, size_t count, off_t offset) { @@ -304,7 +299,7 @@ static GLogColor SeverityToColor(LogSeverity severity) { #ifdef OS_WINDOWS // Returns the character attribute for the given color. -WORD GetColorAttribute(GLogColor color) { +static WORD GetColorAttribute(GLogColor color) { switch (color) { case COLOR_RED: return FOREGROUND_RED; case COLOR_GREEN: return FOREGROUND_GREEN; @@ -316,7 +311,7 @@ WORD GetColorAttribute(GLogColor color) { #else // Returns the ANSI color code for the given color. -const char* GetAnsiColorCode(GLogColor color) { +static const char* GetAnsiColorCode(GLogColor color) { switch (color) { case COLOR_RED: return "1"; case COLOR_GREEN: return "2"; @@ -441,6 +436,7 @@ class LogFileObject : public base::Logger { FILE* file_; LogSeverity severity_; uint32 bytes_since_flush_; + uint32 dropped_mem_length_; uint32 file_length_; unsigned int rollover_attempt_; int64 next_flush_time_; // cycle count at which to flush log @@ -842,6 +838,7 @@ LogFileObject::LogFileObject(LogSeverity severity, file_(NULL), severity_(severity), bytes_since_flush_(0), + dropped_mem_length_(0), file_length_(0), rollover_attempt_(kRolloverAttemptFrequency-1), next_flush_time_(0) { @@ -979,7 +976,7 @@ void LogFileObject::Write(bool force_flush, PidHasChanged()) { if (file_ != NULL) fclose(file_); file_ = NULL; - file_length_ = bytes_since_flush_ = 0; + file_length_ = bytes_since_flush_ = dropped_mem_length_ = 0; rollover_attempt_ = kRolloverAttemptFrequency-1; } @@ -1119,11 +1116,17 @@ void LogFileObject::Write(bool force_flush, (CycleClock_Now() >= next_flush_time_) ) { FlushUnlocked(); #ifdef OS_LINUX - if (FLAGS_drop_log_memory) { - if (file_length_ >= logging::kPageSize) { - // don't evict the most recent page - uint32 len = file_length_ & ~(logging::kPageSize - 1); - posix_fadvise(fileno(file_), 0, len, POSIX_FADV_DONTNEED); + // Only consider files >= 3MiB + if (FLAGS_drop_log_memory && file_length_ >= (3 << 20)) { + // Don't evict the most recent 1-2MiB so as not to impact a tailer + // of the log file and to avoid page rounding issue on linux < 4.7 + uint32 total_drop_length = (file_length_ & ~((1 << 20) - 1)) - (1 << 20); + uint32 this_drop_length = total_drop_length - dropped_mem_length_; + if (this_drop_length >= (2 << 20)) { + // Only advise when >= 2MiB to drop + posix_fadvise(fileno(file_), dropped_mem_length_, this_drop_length, + POSIX_FADV_DONTNEED); + dropped_mem_length_ = total_drop_length; } } #endif @@ -1145,6 +1148,22 @@ static bool fatal_msg_exclusive = true; static LogMessage::LogMessageData fatal_msg_data_exclusive; static LogMessage::LogMessageData fatal_msg_data_shared; +#ifdef GLOG_THREAD_LOCAL_STORAGE +// Static thread-local log data space to use, because typically at most one +// LogMessageData object exists (in this case glog makes zero heap memory +// allocations). +static GLOG_THREAD_LOCAL_STORAGE bool thread_data_available = true; + +#ifdef HAVE_ALIGNED_STORAGE +static GLOG_THREAD_LOCAL_STORAGE + std::aligned_storage<sizeof(LogMessage::LogMessageData), + alignof(LogMessage::LogMessageData)>::type thread_msg_data; +#else +static GLOG_THREAD_LOCAL_STORAGE + char thread_msg_data[sizeof(void*) + sizeof(LogMessage::LogMessageData)]; +#endif // HAVE_ALIGNED_STORAGE +#endif // defined(GLOG_THREAD_LOCAL_STORAGE) + LogMessage::LogMessageData::LogMessageData() : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) { } @@ -1201,8 +1220,28 @@ void LogMessage::Init(const char* file, void (LogMessage::*send_method)()) { allocated_ = NULL; if (severity != GLOG_FATAL || !exit_on_dfatal) { +#ifdef GLOG_THREAD_LOCAL_STORAGE + // No need for locking, because this is thread local. + if (thread_data_available) { + thread_data_available = false; +#ifdef HAVE_ALIGNED_STORAGE + data_ = new (&thread_msg_data) LogMessageData; +#else + const uintptr_t kAlign = sizeof(void*) - 1; + + char* align_ptr = + reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(thread_msg_data + kAlign) & ~kAlign); + data_ = new (align_ptr) LogMessageData; + assert(reinterpret_cast<uintptr_t>(align_ptr) % sizeof(void*) == 0); +#endif + } else { + allocated_ = new LogMessageData(); + data_ = allocated_; + } +#else // !defined(GLOG_THREAD_LOCAL_STORAGE) allocated_ = new LogMessageData(); data_ = allocated_; +#endif // defined(GLOG_THREAD_LOCAL_STORAGE) data_->first_fatal_ = false; } else { MutexLock l(&fatal_msg_lock); @@ -1227,7 +1266,6 @@ void LogMessage::Init(const char* file, data_->timestamp_ = static_cast<time_t>(now); localtime_r(&data_->timestamp_, &data_->tm_time_); int usecs = static_cast<int>((now - data_->timestamp_) * 1000000); - RawLog__SetLastTime(data_->tm_time_, usecs); data_->num_chars_to_log_ = 0; data_->num_chars_to_syslog_ = 0; @@ -1271,7 +1309,17 @@ void LogMessage::Init(const char* file, LogMessage::~LogMessage() { Flush(); +#ifdef GLOG_THREAD_LOCAL_STORAGE + if (data_ == static_cast<void*>(&thread_msg_data)) { + data_->~LogMessageData(); + thread_data_available = true; + } + else { + delete allocated_; + } +#else // !defined(GLOG_THREAD_LOCAL_STORAGE) delete allocated_; +#endif // defined(GLOG_THREAD_LOCAL_STORAGE) } int LogMessage::preserved_errno() const { @@ -1466,16 +1514,13 @@ void LogMessage::RecordCrashReason( # define ATTRIBUTE_NORETURN #endif +#if defined(OS_WINDOWS) +__declspec(noreturn) +#endif static void logging_fail() ATTRIBUTE_NORETURN; static void logging_fail() { -#if defined(_DEBUG) && defined(_MSC_VER) - // When debugging on windows, avoid the obnoxious dialog and make - // it possible to continue past a LOG(FATAL) in the debugger - __debugbreak(); -#else abort(); -#endif } typedef void (*logging_fail_func_t)() ATTRIBUTE_NORETURN; @@ -1681,6 +1726,7 @@ void LogToStderr() { namespace base { namespace internal { +bool GetExitOnDFatal(); bool GetExitOnDFatal() { MutexLock l(&log_mutex); return exit_on_dfatal; @@ -1696,6 +1742,7 @@ bool GetExitOnDFatal() { // and the stack trace is not recorded. The LOG(FATAL) *will* still // exit the program. Since this function is used only in testing, // these differences are acceptable. +void SetExitOnDFatal(bool value); void SetExitOnDFatal(bool value) { MutexLock l(&log_mutex); exit_on_dfatal = value; @@ -1704,6 +1751,42 @@ void SetExitOnDFatal(bool value) { } // namespace internal } // namespace base +// Shell-escaping as we need to shell out ot /bin/mail. +static const char kDontNeedShellEscapeChars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+-_.=/:,@"; + +static string ShellEscape(const string& src) { + string result; + if (!src.empty() && // empty string needs quotes + src.find_first_not_of(kDontNeedShellEscapeChars) == string::npos) { + // only contains chars that don't need quotes; it's fine + result.assign(src); + } else if (src.find_first_of('\'') == string::npos) { + // no single quotes; just wrap it in single quotes + result.assign("'"); + result.append(src); + result.append("'"); + } else { + // needs double quote escaping + result.assign("\""); + for (size_t i = 0; i < src.size(); ++i) { + switch (src[i]) { + case '\\': + case '$': + case '"': + case '`': + result.append("\\"); + } + result.append(src, i, 1); + } + result.append("\""); + } + return result; +} + + // use_logging controls whether the logging functions LOG/VLOG are used // to log errors. It should be set to false when the caller holds the // log_mutex. @@ -1719,7 +1802,10 @@ static bool SendEmailInternal(const char*dest, const char *subject, } string cmd = - FLAGS_logmailer + " -s\"" + subject + "\" " + dest; + FLAGS_logmailer + " -s" + + ShellEscape(subject) + " " + ShellEscape(dest); + VLOG(4) << "Mailing command: " << cmd; + FILE* pipe = popen(cmd.c_str(), "w"); if (pipe != NULL) { // Add the body if we have one |