Bug 1513057 - P3: Setup memory reporter on socket process r=dragana,mayhemer
☠☠ backed out by 3f76ed638d83 ☠ ☠
authorKershaw Chang <kershaw@mozilla.com>
Fri, 11 Jan 2019 13:28:00 +0000
changeset 510576 a81f83df08d50ced7d669958f9a06f52b087a5fc
parent 510575 edbda5ee5fd53f9ba0ab75477f08c7b29088eca1
child 510577 86032a14d26fc5be8c6802ec915db14e1a371b6c
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana, mayhemer
bugs1513057
milestone66.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 1513057 - P3: Setup memory reporter on socket process r=dragana,mayhemer To setup memory reporter on socket process, this patch modifies the PSocketProcess protocol to implement the same memory reporting functions as the PContent and PGPU protocols. Differential Revision: https://phabricator.services.mozilla.com/D14155
netwerk/base/nsIOService.cpp
netwerk/base/nsIOService.h
netwerk/ipc/PSocketProcess.ipdl
netwerk/ipc/SocketProcessChild.cpp
netwerk/ipc/SocketProcessChild.h
netwerk/ipc/SocketProcessHost.cpp
netwerk/ipc/SocketProcessHost.h
netwerk/ipc/SocketProcessParent.cpp
netwerk/ipc/SocketProcessParent.h
xpcom/base/moz.build
xpcom/base/nsMemoryReporterManager.cpp
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -464,16 +464,27 @@ void nsIOService::OnProcessLaunchComplet
 
 void nsIOService::OnProcessUnexpectedShutdown(SocketProcessHost *aHost) {
   MOZ_ASSERT(NS_IsMainThread());
 
   LOG(("nsIOService::OnProcessUnexpectedShutdown\n"));
   DestroySocketProcess();
 }
 
+RefPtr<MemoryReportingProcess> nsIOService::GetSocketProcessMemoryReporter() {
+  // Check the prefs here again, since we don't want to create
+  // SocketProcessMemoryReporter for some tests.
+  if (!Preferences::GetBool("network.process.enabled") || !SocketProcessReady()) {
+    return nullptr;
+
+  }
+
+  return new SocketProcessMemoryReporter();
+}
+
 NS_IMPL_ISUPPORTS(nsIOService, nsIIOService, nsINetUtil, nsISpeculativeConnect,
                   nsIObserver, nsIIOServiceInternal, nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 
 nsresult nsIOService::RecheckCaptivePortal() {
   MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread");
   if (!mCaptivePortalService) {
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -40,20 +40,22 @@ static const char gForcedExternalSchemes
 
 class nsINetworkLinkService;
 class nsIPrefBranch;
 class nsIProtocolProxyService2;
 class nsIProxyInfo;
 class nsPISocketTransportService;
 
 namespace mozilla {
+class MemoryReportingProcess;
 namespace net {
 class NeckoChild;
 class nsAsyncRedirectVerifyHelper;
 class SocketProcessHost;
+class SocketProcessMemoryReporter;
 
 class nsIOService final : public nsIIOService,
                           public nsIObserver,
                           public nsINetUtil,
                           public nsISpeculativeConnect,
                           public nsSupportsWeakReference,
                           public nsIIOServiceInternal {
  public:
@@ -114,16 +116,19 @@ class nsIOService final : public nsIIOSe
   // Used to trigger a recheck of the captive portal status
   nsresult RecheckCaptivePortal();
 
   void OnProcessLaunchComplete(SocketProcessHost* aHost, bool aSucceeded);
   void OnProcessUnexpectedShutdown(SocketProcessHost* aHost);
   bool SocketProcessReady();
   void NotifySocketProcessPrefsChanged(const char* aName);
 
+  friend SocketProcessMemoryReporter;
+  RefPtr<MemoryReportingProcess> GetSocketProcessMemoryReporter();
+
  private:
   // These shouldn't be called directly:
   // - construct using GetInstance
   // - destroy using Release
   nsIOService();
   ~nsIOService();
   nsresult SetConnectivityInternal(bool aConnectivity);
 
--- a/netwerk/ipc/PSocketProcess.ipdl
+++ b/netwerk/ipc/PSocketProcess.ipdl
@@ -1,23 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+include MemoryReportTypes;
 include PrefsTypes;
 
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 
 namespace mozilla {
 namespace net {
 
 protocol PSocketProcess
 {
 parent:
   async InitCrashReporter(Shmem shmem, NativeThreadId threadId);
+  async AddMemoryReport(MemoryReport aReport);
+  async FinishMemoryReport(uint32_t aGeneration);
 
 child:
   async PreferenceUpdate(Pref pref);
+  async RequestMemoryReport(uint32_t generation,
+                            bool anonymize,
+                            bool minimizeMemoryUsage,
+                            MaybeFileDesc DMDFile);
 };
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.cpp
+++ b/netwerk/ipc/SocketProcessChild.cpp
@@ -3,38 +3,47 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SocketProcessChild.h"
 #include "SocketProcessLogging.h"
 
 #include "base/task.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/ipc/CrashReporterClient.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/Preferences.h"
 #include "nsDebugImpl.h"
 #include "nsThreadManager.h"
 #include "ProcessUtils.h"
 
 namespace mozilla {
 namespace net {
 
 using namespace ipc;
 
+static SocketProcessChild* sSocketProcessChild;
+
 SocketProcessChild::SocketProcessChild() {
   LOG(("CONSTRUCT SocketProcessChild::SocketProcessChild\n"));
   nsDebugImpl::SetMultiprocessMode("Socket");
 
   MOZ_COUNT_CTOR(SocketProcessChild);
+  sSocketProcessChild = this;
 }
 
 SocketProcessChild::~SocketProcessChild() {
   LOG(("DESTRUCT SocketProcessChild::SocketProcessChild\n"));
   MOZ_COUNT_DTOR(SocketProcessChild);
+  sSocketProcessChild = nullptr;
+}
+
+/* static */ SocketProcessChild* SocketProcessChild::GetSingleton() {
+  return sSocketProcessChild;
 }
 
 bool SocketProcessChild::Init(base::ProcessId aParentPid,
                               const char* aParentBuildID, MessageLoop* aIOLoop,
                               IPC::Channel* aChannel) {
   if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
     return false;
   }
@@ -76,10 +85,26 @@ void SocketProcessChild::CleanUp() {
   NS_ShutdownXPCOM(nullptr);
 }
 
 IPCResult SocketProcessChild::RecvPreferenceUpdate(const Pref& aPref) {
   Preferences::SetPreference(aPref);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult SocketProcessChild::RecvRequestMemoryReport(
+    const uint32_t& aGeneration, const bool& aAnonymize,
+    const bool& aMinimizeMemoryUsage, const MaybeFileDesc& aDMDFile) {
+  nsPrintfCString processName("SocketProcess");
+
+  mozilla::dom::MemoryReportRequestClient::Start(
+      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
+      [&](const MemoryReport& aReport) {
+        Unused << GetSingleton()->SendAddMemoryReport(aReport);
+      },
+      [&](const uint32_t& aGeneration) {
+        return GetSingleton()->SendFinishMemoryReport(aGeneration);
+      });
+  return IPC_OK();
+}
+
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.h
+++ b/netwerk/ipc/SocketProcessChild.h
@@ -13,22 +13,28 @@ namespace net {
 
 // The IPC actor implements PSocketProcessChild in child process.
 // This is allocated and kept alive by SocketProcessImpl.
 class SocketProcessChild final : public PSocketProcessChild {
  public:
   SocketProcessChild();
   ~SocketProcessChild();
 
+  static SocketProcessChild* GetSingleton();
+
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
             MessageLoop* aIOLoop, IPC::Channel* aChannel);
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& aPref) override;
+  mozilla::ipc::IPCResult RecvRequestMemoryReport(
+      const uint32_t& generation, const bool& anonymize,
+      const bool& minimizeMemoryUsage, const MaybeFileDesc& DMDFile) override;
+
   void CleanUp();
 
  private:
 };
 
 }  // namespace net
 }  // namespace mozilla
 
--- a/netwerk/ipc/SocketProcessHost.cpp
+++ b/netwerk/ipc/SocketProcessHost.cpp
@@ -199,10 +199,55 @@ void SocketProcessHost::DestroyProcess()
     MonitorAutoLock lock(mMonitor);
     mTaskFactory.RevokeAll();
   }
 
   MessageLoop::current()->PostTask(NewRunnableFunction(
       "DestroySocketProcessRunnable", DelayedDeleteSubprocess, this));
 }
 
+//-----------------------------------------------------------------------------
+// SocketProcessMemoryReporter
+//-----------------------------------------------------------------------------
+
+bool SocketProcessMemoryReporter::IsAlive() const {
+  MOZ_ASSERT(gIOService);
+
+  if (!gIOService->mSocketProcess) {
+    return false;
+  }
+
+  return gIOService->mSocketProcess->IsConnected();
+}
+
+bool SocketProcessMemoryReporter::SendRequestMemoryReport(
+    const uint32_t& aGeneration, const bool& aAnonymize,
+    const bool& aMinimizeMemoryUsage, const dom::MaybeFileDesc& aDMDFile) {
+  MOZ_ASSERT(gIOService);
+
+  if (!gIOService->mSocketProcess) {
+    return false;
+  }
+
+  SocketProcessParent* actor = gIOService->mSocketProcess->GetActor();
+  if (!actor) {
+    return false;
+  }
+
+  return actor->SendRequestMemoryReport(aGeneration, aAnonymize,
+                                        aMinimizeMemoryUsage, aDMDFile);
+}
+
+int32_t SocketProcessMemoryReporter::Pid() const {
+  MOZ_ASSERT(gIOService);
+
+  if (!gIOService->mSocketProcess) {
+    return 0;
+  }
+
+  if (SocketProcessParent* actor = gIOService->mSocketProcess->GetActor()) {
+    return (int32_t)actor->OtherPid();
+  }
+  return 0;
+}
+
 }  // namespace net
 }  // namespace mozilla
--- a/netwerk/ipc/SocketProcessHost.h
+++ b/netwerk/ipc/SocketProcessHost.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_net_SocketProcessHost_h
 #define mozilla_net_SocketProcessHost_h
 
 #include "mozilla/UniquePtr.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
+#include "mozilla/MemoryReportingProcess.h"
 #include "mozilla/ipc/TaskFactory.h"
 
 namespace mozilla {
 namespace net {
 
 class SocketProcessParent;
 
 // SocketProcessHost is the "parent process" container for a subprocess handle
@@ -97,12 +98,31 @@ class SocketProcessHost final : public m
   UniquePtr<SocketProcessParent> mSocketProcessParent;
   // mShutdownRequested is set to true only when Shutdown() is called.
   // If mShutdownRequested is false and the IPC channel is closed,
   // OnProcessUnexpectedShutdown will be invoked.
   bool mShutdownRequested;
   bool mChannelClosed;
 };
 
+class SocketProcessMemoryReporter : public MemoryReportingProcess {
+ public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SocketProcessMemoryReporter, override)
+
+  SocketProcessMemoryReporter() = default;
+
+  bool IsAlive() const override;
+
+  bool SendRequestMemoryReport(const uint32_t& aGeneration,
+                               const bool& aAnonymize,
+                               const bool& aMinimizeMemoryUsage,
+                               const dom::MaybeFileDesc& aDMDFile) override;
+
+  int32_t Pid() const override;
+
+ protected:
+  virtual ~SocketProcessMemoryReporter() = default;
+};
+
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // mozilla_net_SocketProcessHost_h
--- a/netwerk/ipc/SocketProcessParent.cpp
+++ b/netwerk/ipc/SocketProcessParent.cpp
@@ -38,16 +38,42 @@ void SocketProcessParent::ActorDestroy(A
     }
   }
 
   if (mHost) {
     mHost->OnChannelClosed();
   }
 }
 
+bool SocketProcessParent::SendRequestMemoryReport(
+    const uint32_t& aGeneration, const bool& aAnonymize,
+    const bool& aMinimizeMemoryUsage, const MaybeFileDesc& aDMDFile) {
+  mMemoryReportRequest = MakeUnique<dom::MemoryReportRequestHost>(aGeneration);
+  Unused << PSocketProcessParent::SendRequestMemoryReport(
+      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
+  return true;
+}
+
+mozilla::ipc::IPCResult SocketProcessParent::RecvAddMemoryReport(
+    const MemoryReport& aReport) {
+  if (mMemoryReportRequest) {
+    mMemoryReportRequest->RecvReport(aReport);
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult SocketProcessParent::RecvFinishMemoryReport(
+    const uint32_t& aGeneration) {
+  if (mMemoryReportRequest) {
+    mMemoryReportRequest->Finish(aGeneration);
+    mMemoryReportRequest = nullptr;
+  }
+  return IPC_OK();
+}
+
 // To ensure that IPDL is finished before SocketParent gets deleted.
 class DeferredDeleteSocketProcessParent : public Runnable {
  public:
   explicit DeferredDeleteSocketProcessParent(
       UniquePtr<SocketProcessParent>&& aParent)
       : Runnable("net::DeferredDeleteSocketProcessParent"),
         mParent(std::move(aParent)) {}
 
--- a/netwerk/ipc/SocketProcessParent.h
+++ b/netwerk/ipc/SocketProcessParent.h
@@ -6,16 +6,21 @@
 #ifndef mozilla_net_SocketProcessParent_h
 #define mozilla_net_SocketProcessParent_h
 
 #include "mozilla/UniquePtr.h"
 #include "mozilla/net/PSocketProcessParent.h"
 
 namespace mozilla {
 
+namespace dom {
+class MemoryReport;
+class MemoryReportRequestHost;
+}  // namespace dom
+
 namespace ipc {
 class CrashReporterHost;
 }  // namespace ipc
 
 namespace net {
 
 class SocketProcessHost;
 
@@ -25,22 +30,31 @@ class SocketProcessParent final : public
  public:
   friend class SocketProcessHost;
 
   explicit SocketProcessParent(SocketProcessHost* aHost);
   ~SocketProcessParent();
 
   mozilla::ipc::IPCResult RecvInitCrashReporter(
       Shmem&& aShmem, const NativeThreadId& aThreadId) override;
+  mozilla::ipc::IPCResult RecvAddMemoryReport(
+      const MemoryReport& aReport) override;
+  mozilla::ipc::IPCResult RecvFinishMemoryReport(
+      const uint32_t& aGeneration) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
+  bool SendRequestMemoryReport(const uint32_t& aGeneration,
+                               const bool& aAnonymize,
+                               const bool& aMinimizeMemoryUsage,
+                               const MaybeFileDesc& aDMDFile);
 
  private:
   SocketProcessHost* mHost;
   UniquePtr<ipc::CrashReporterHost> mCrashReporter;
+  UniquePtr<dom::MemoryReportRequestHost> mMemoryReportRequest;
 
   static void Destroy(UniquePtr<SocketProcessParent>&& aParent);
 };
 
 }  // namespace net
 }  // namespace mozilla
 
 #endif  // mozilla_net_SocketProcessParent_h
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -215,16 +215,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wi
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../build',
     '/dom/base',
     '/mfbt',
+    '/netwerk/base',
     '/xpcom/ds',
 ]
 
 if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     CXXFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['ENABLE_CLANG_PLUGIN'] and CONFIG['CC_TYPE'] == 'clang-cl':
     AllowCompilerWarnings()  # workaround for bug 1090497
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -11,16 +11,17 @@
 #include "nsPrintfCString.h"
 #include "nsProxyRelease.h"
 #include "nsServiceManagerUtils.h"
 #include "nsMemoryReporterManager.h"
 #include "nsITimer.h"
 #include "nsThreadUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIObserverService.h"
+#include "nsIOService.h"
 #include "nsIGlobalObject.h"
 #include "nsIXPConnect.h"
 #ifdef MOZ_GECKO_PROFILER
 #include "GeckoProfilerReporter.h"
 #endif
 #if defined(XP_UNIX) || defined(MOZ_DMD)
 #include "nsMemoryInfoDumper.h"
 #endif
@@ -1808,16 +1809,23 @@ nsresult nsMemoryReporterManager::StartG
   }
 
   if (RDDProcessManager* rdd = RDDProcessManager::Get()) {
     if (RefPtr<MemoryReportingProcess> proc = rdd->GetProcessMemoryReporter()) {
       s->mChildrenPending.AppendElement(proc.forget());
     }
   }
 
+  if (net::gIOService) {
+    if (RefPtr<MemoryReportingProcess> proc =
+            net::gIOService->GetSocketProcessMemoryReporter()) {
+      s->mChildrenPending.AppendElement(proc.forget());
+    }
+  }
+
   if (!s->mChildrenPending.IsEmpty()) {
     nsCOMPtr<nsITimer> timer;
     rv = NS_NewTimerWithFuncCallback(
         getter_AddRefs(timer), TimeoutCallback, this, kTimeoutLengthMS,
         nsITimer::TYPE_ONE_SHOT,
         "nsMemoryReporterManager::StartGettingReports");
     if (NS_WARN_IF(NS_FAILED(rv))) {
       FinishReporting();