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 180602 f628c9d48728aa58d314e3f7b8cf5d235cb14a52
parent 180601 60b6bdaafba7b8b5ee5acb7a295f6f13402d1e72
child 180603 4e47286ce9b73b661b29ea24ff009e90b563dc19
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersfroydnj
bugs1001137
milestone31.0a1
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()) {