Fix initialization ordering problem in logging code. Based on patch from Wink Saville.

pull/3335/head
kenton@google.com 16 years ago
parent cfa2d8aa87
commit 6dcd46c8d2
  1. 2
      CONTRIBUTORS.txt
  2. 28
      src/google/protobuf/stubs/common.cc

@ -63,3 +63,5 @@ Patch contributors:
* Fixed warnings about generated constructors not explicitly initializing
all fields (only present with certain compiler settings).
* Added generation of field number constants.
Wink Saville <wink@google.com>
* Fixed initialization ordering problem in logging code.

@ -113,7 +113,27 @@ void NullLogHandler(LogLevel level, const char* filename, int line,
static LogHandler* log_handler_ = &DefaultLogHandler;
static int log_silencer_count_ = 0;
static Mutex log_silencer_count_mutex_;
// Mutex which protects log_silencer_count_. We provide a static function to
// get it so that it is initialized on first use, which be during
// initialization time. If we just allocated it as a global variable, it might
// not be initialized before someone tries to use it.
static Mutex* LogSilencerMutex() {
static Mutex* log_silencer_count_mutex_ = new Mutex;
return log_silencer_count_mutex_;
}
// Forces the above mutex to be initialized during startup. This way we don't
// have to worry about the initialization itself being thread-safe, since no
// threads should exist yet at startup time. (Otherwise we'd have no way to
// make things thread-safe here because we'd need a Mutex for that, and we'd
// have no way to construct one safely!)
static struct LogSilencerMutexInitializer {
LogSilencerMutexInitializer() {
LogSilencerMutex();
}
} log_silencer_mutex_initializer;
static string SimpleCtoa(char c) { return string(1, c); }
@ -140,7 +160,7 @@ void LogMessage::Finish() {
bool suppress = false;
if (level_ != LOGLEVEL_FATAL) {
MutexLock lock(&internal::log_silencer_count_mutex_);
MutexLock lock(internal::LogSilencerMutex());
suppress = internal::log_silencer_count_ > 0;
}
@ -173,12 +193,12 @@ LogHandler* SetLogHandler(LogHandler* new_func) {
}
LogSilencer::LogSilencer() {
MutexLock lock(&internal::log_silencer_count_mutex_);
MutexLock lock(internal::LogSilencerMutex());
++internal::log_silencer_count_;
};
LogSilencer::~LogSilencer() {
MutexLock lock(&internal::log_silencer_count_mutex_);
MutexLock lock(internal::LogSilencerMutex());
--internal::log_silencer_count_;
};

Loading…
Cancel
Save