Bug 1001137 - Enabling FifoWatcher via user pref does not work. r=froydnj
authorEric Rahm <erahm@mozilla.com>
Thu, 24 Apr 2014 15:58:57 -0700
changeset 198820 f628c9d48728aa58d314e3f7b8cf5d235cb14a52
parent 198819 60b6bdaafba7b8b5ee5acb7a295f6f13402d1e72
child 198821 4e47286ce9b73b661b29ea24ff009e90b563dc19
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1001137
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1001137 - Enabling FifoWatcher via user pref does not work. r=froydnj
modules/libpref/src/init/all.js
xpcom/base/nsDumpUtils.cpp
xpcom/base/nsDumpUtils.h
xpcom/base/nsMemoryInfoDumper.cpp
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -4355,17 +4355,17 @@ pref("ui.touch_activation.delay_ms", 100
 
 // If the user has clicked an element, how long do we keep the
 // :active state before it is cleared by the mouse sequences
 // fired after a touchstart/touchend.
 pref("ui.touch_activation.duration_ms", 10);
 
 // nsMemoryInfoDumper can watch a fifo in the temp directory and take various
 // actions when the fifo is written to.  Disable this in general.
-pref("memory_info_dumper.watch_fifo", false);
+pref("memory_info_dumper.watch_fifo.enabled", false);
 
 #ifdef MOZ_CAPTIVEDETECT
 pref("captivedetect.maxWaitingTime", 5000);
 pref("captivedetect.pollingTime", 3000);
 pref("captivedetect.maxRetryCount", 5);
 #endif
 
 #ifdef RELEASE_BUILD
--- a/xpcom/base/nsDumpUtils.cpp
+++ b/xpcom/base/nsDumpUtils.cpp
@@ -43,16 +43,19 @@ using namespace mozilla;
  * But that uses libevent, which does not handle the realtime signals (bug
  * 794074).
  */
 
 // This is the write-end of a pipe that we use to notice when a
 // specific signal occurs.
 static Atomic<int> sDumpPipeWriteFd(-1);
 
+const char* const FifoWatcher::kPrefName =
+    "memory_info_dumper.watch_fifo.enabled";
+
 static void
 DumpSignalHandler(int aSignum)
 {
   // This is a signal handler, so everything in here needs to be
   // async-signal-safe.  Be careful!
 
   if (sDumpPipeWriteFd != -1) {
     uint8_t signum = static_cast<int>(aSignum);
@@ -234,18 +237,17 @@ void SignalPipeWatcher::OnFileCanReadWit
 
 StaticRefPtr<FifoWatcher> FifoWatcher::sSingleton;
 
 /* static */ FifoWatcher*
 FifoWatcher::GetSingleton()
 {
   if (!sSingleton) {
     nsAutoCString dirPath;
-    Preferences::GetCString(
-      "memory_info_dumper.watch_fifo.directory", &dirPath);
+    Preferences::GetCString(kPrefName, &dirPath);
     sSingleton = new FifoWatcher(dirPath);
     sSingleton->Init();
     ClearOnShutdown(&sSingleton);
   }
   return sSingleton;
 }
 
 /* static */ bool
--- a/xpcom/base/nsDumpUtils.h
+++ b/xpcom/base/nsDumpUtils.h
@@ -103,16 +103,21 @@ struct FifoInfo {
   nsCString mCommand;
   FifoCallback mCallback;
 };
 typedef nsTArray<FifoInfo> FifoInfoArray;
 
 class FifoWatcher : public FdWatcher
 {
 public:
+  /**
+   * The name of the preference used to enable/disable the FifoWatcher.
+   */
+  static const char* const kPrefName;
+
   static FifoWatcher* GetSingleton();
 
   static bool MaybeCreate();
 
   void RegisterCallback(const nsCString& aCommand, FifoCallback aCallback);
 
   virtual ~FifoWatcher();
 
--- a/xpcom/base/nsMemoryInfoDumper.cpp
+++ b/xpcom/base/nsMemoryInfoDumper.cpp
@@ -27,16 +27,17 @@
 #else
 #include <unistd.h>
 #endif
 
 #if defined(XP_LINUX) || defined(__FreeBSD__)
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include "mozilla/Preferences.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace {
 
 class DumpMemoryInfoToTempDirRunnable : public nsRunnable
@@ -162,16 +163,53 @@ void doGCCCDump(const uint8_t recvSig)
   nsRefPtr<GCAndCCLogDumpRunnable> runnable =
     new GCAndCCLogDumpRunnable(
         /* identifier = */ EmptyString(),
         /* allTraces = */ true,
         /* dumpChildProcesses = */ true);
   NS_DispatchToMainThread(runnable);
 }
 
+bool SetupFifo()
+{
+  static bool fifoCallbacksRegistered = false;
+
+  if (!FifoWatcher::MaybeCreate()) {
+    return false;
+  }
+
+  MOZ_ASSERT(!fifoCallbacksRegistered,
+             "FifoWatcher callbacks should be registered only once");
+
+  FifoWatcher* fw = FifoWatcher::GetSingleton();
+  // Dump our memory reports (but run this on the main thread!).
+  fw->RegisterCallback(NS_LITERAL_CSTRING("memory report"),
+                       doMemoryReport);
+  fw->RegisterCallback(NS_LITERAL_CSTRING("minimize memory report"),
+                       doMemoryReport);
+  // Dump GC and CC logs (from the main thread).
+  fw->RegisterCallback(NS_LITERAL_CSTRING("gc log"),
+                       doGCCCDump);
+  fw->RegisterCallback(NS_LITERAL_CSTRING("abbreviated gc log"),
+                       doGCCCDump);
+
+  fifoCallbacksRegistered = true;
+  return true;
+}
+
+void OnFifoEnabledChange(const char* /*unused*/, void* /*unused*/)
+{
+  LOG("%s changed", FifoWatcher::kPrefName);
+  if (SetupFifo()) {
+    Preferences::UnregisterCallback(OnFifoEnabledChange,
+                                    FifoWatcher::kPrefName,
+                                    nullptr);
+  }
+}
+
 } // anonymous namespace
 #endif // XP_LINUX }
 
 NS_IMPL_ISUPPORTS1(nsMemoryInfoDumper, nsIMemoryInfoDumper)
 
 nsMemoryInfoDumper::nsMemoryInfoDumper()
 {
 }
@@ -191,28 +229,24 @@ nsMemoryInfoDumper::Initialize()
   sw->RegisterCallback(sDumpAboutMemorySignum, doMemoryReport);
   // Dump our memory reporters after minimizing memory usage
   sDumpAboutMemoryAfterMMUSignum = SIGRTMIN + 1;
   sw->RegisterCallback(sDumpAboutMemoryAfterMMUSignum, doMemoryReport);
   // Dump the GC and CC logs in this and our child processes.
   sGCAndCCDumpSignum = SIGRTMIN + 2;
   sw->RegisterCallback(sGCAndCCDumpSignum, doGCCCDump);
 
-  if (FifoWatcher::MaybeCreate()) {
-    FifoWatcher* fw = FifoWatcher::GetSingleton();
-    // Dump our memory reports (but run this on the main thread!).
-    fw->RegisterCallback(NS_LITERAL_CSTRING("memory report"),
-                         doMemoryReport);
-    fw->RegisterCallback(NS_LITERAL_CSTRING("minimize memory report"),
-                         doMemoryReport);
-    // Dump GC and CC logs (from the main thread).
-    fw->RegisterCallback(NS_LITERAL_CSTRING("gc log"),
-                         doGCCCDump);
-    fw->RegisterCallback(NS_LITERAL_CSTRING("abbreviated gc log"),
-                         doGCCCDump);
+  if (!SetupFifo()) {
+    // NB: This gets loaded early enough that it's possible there is a user pref
+    //     set to enable the fifo watcher that has not been loaded yet. Register
+    //     to attempt to initialize if the fifo watcher becomes enabled by
+    //     a user pref.
+    Preferences::RegisterCallback(OnFifoEnabledChange,
+                                  FifoWatcher::kPrefName,
+                                  nullptr);
   }
 #endif
 }
 
 static void
 EnsureNonEmptyIdentifier(nsAString& aIdentifier)
 {
   if (!aIdentifier.IsEmpty()) {