Commits

Anonymous committed b2cee15

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

Comments (0)

Files changed (2)

     * 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.

src/google/protobuf/stubs/common.cc

 
 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); }
 
   bool suppress = false;
 
   if (level_ != LOGLEVEL_FATAL) {
-    MutexLock lock(&internal::log_silencer_count_mutex_);
+    MutexLock lock(internal::LogSilencerMutex());
     suppress = internal::log_silencer_count_ > 0;
   }
 
 }
 
 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_;
 };