Bug 1125030 - Handle VsyncChild shutdown in ActorDestroy(). r=bent
authorJerryShih <hshih@mozilla.com>
Thu, 29 Jan 2015 22:19:00 +0100
changeset 226793 e51f02d321f98580e1d708854fc722069afc4e6b
parent 226792 8d3180c7e7cd43a608868c9c9a88ebc41867b4d5
child 226794 8497232f9bb23dd4aa4f582278e8107eb94d4c6c
push id28205
push userryanvm@gmail.com
push dateFri, 30 Jan 2015 17:32:20 +0000
treeherdermozilla-central@d7e156a7a0a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs1125030
milestone38.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 1125030 - Handle VsyncChild shutdown in ActorDestroy(). r=bent
ipc/glue/BackgroundChildImpl.cpp
layout/base/nsRefreshDriver.cpp
layout/ipc/VsyncChild.cpp
layout/ipc/VsyncChild.h
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -185,25 +185,30 @@ BackgroundChildImpl::DeallocPFileDescrip
 
   delete static_cast<FileDescriptorSetChild*>(aActor);
   return true;
 }
 
 BackgroundChildImpl::PVsyncChild*
 BackgroundChildImpl::AllocPVsyncChild()
 {
-  return new mozilla::layout::VsyncChild();
+  nsRefPtr<mozilla::layout::VsyncChild> actor = new mozilla::layout::VsyncChild();
+  // There still has one ref-count after return, and it will be released in
+  // DeallocPVsyncChild().
+  return actor.forget().take();
 }
 
 bool
 BackgroundChildImpl::DeallocPVsyncChild(PVsyncChild* aActor)
 {
   MOZ_ASSERT(aActor);
 
-  delete static_cast<mozilla::layout::VsyncChild*>(aActor);
+  // This actor already has one ref-count. Please check AllocPVsyncChild().
+  nsRefPtr<mozilla::layout::VsyncChild> actor =
+      dont_AddRef(static_cast<mozilla::layout::VsyncChild*>(aActor));
   return true;
 }
 
 // -----------------------------------------------------------------------------
 // BroadcastChannel API
 // -----------------------------------------------------------------------------
 
 dom::PBroadcastChannelChild*
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -435,19 +435,23 @@ private:
   void RunRefreshDrivers(TimeStamp aTimeStamp)
   {
     int64_t jsnow = JS_Now();
     TimeDuration diff = TimeStamp::Now() - aTimeStamp;
     int64_t vsyncJsNow = jsnow - diff.ToMicroseconds();
     Tick(vsyncJsNow, aTimeStamp);
   }
 
+  nsRefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
+  // Used for parent process.
   nsRefPtr<RefreshTimerVsyncDispatcher> mVsyncDispatcher;
-  nsRefPtr<RefreshDriverVsyncObserver> mVsyncObserver;
-  VsyncChild* mVsyncChild;
+  // Used for child process.
+  // The mVsyncChild will be always available before VsncChild::ActorDestroy().
+  // After ActorDestroy(), StartTimer() and StopTimer() calls will be non-op.
+  nsRefPtr<VsyncChild> mVsyncChild;
 }; // VsyncRefreshDriverTimer
 
 /*
  * PreciseRefreshDriverTimer schedules ticks based on the current time
  * and when the next tick -should- be sent if we were hitting our
  * rate.  It always schedules ticks on multiples of aRate -- meaning that
  * if some execution takes longer than an alloted slot, the next tick
  * will be delayed instead of triggering instantly.  This might not be
--- a/layout/ipc/VsyncChild.cpp
+++ b/layout/ipc/VsyncChild.cpp
@@ -8,58 +8,62 @@
 #include "mozilla/VsyncDispatcher.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace layout {
 
 VsyncChild::VsyncChild()
   : mObservingVsync(false)
+  , mIsShutdown(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 VsyncChild::~VsyncChild()
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 bool
 VsyncChild::SendObserve()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (!mObservingVsync) {
+  if (!mObservingVsync && !mIsShutdown) {
+    mObservingVsync = true;
     PVsyncChild::SendObserve();
-    mObservingVsync = true;
   }
   return true;
 }
 
 bool
 VsyncChild::SendUnobserve()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (mObservingVsync) {
+  if (mObservingVsync && !mIsShutdown) {
+    mObservingVsync = false;
     PVsyncChild::SendUnobserve();
-    mObservingVsync = false;
   }
   return true;
 }
 
 void
 VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mIsShutdown);
+  mIsShutdown = true;
   mObserver = nullptr;
 }
 
 bool
 VsyncChild::RecvNotify(const TimeStamp& aVsyncTimestamp)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mIsShutdown);
   if (mObservingVsync && mObserver) {
     mObserver->NotifyVsync(aVsyncTimestamp);
   }
   return true;
 }
 
 void
 VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver)
--- a/layout/ipc/VsyncChild.h
+++ b/layout/ipc/VsyncChild.h
@@ -2,16 +2,17 @@
 /* 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/. */
 
 #ifndef mozilla_layout_ipc_VsyncChild_h
 #define mozilla_layout_ipc_VsyncChild_h
 
 #include "mozilla/layout/PVsyncChild.h"
+#include "nsISupportsImpl.h"
 #include "nsRefPtr.h"
 
 namespace mozilla {
 
 class VsyncObserver;
 
 namespace ipc {
 class BackgroundChildImpl;
@@ -20,16 +21,18 @@ class BackgroundChildImpl;
 namespace layout {
 
 // The PVsyncChild actor receives a vsync event from the main process and
 // delivers it to the child process. Currently this is restricted to the main
 // thread only. The actor will stay alive until the process dies or its
 // PVsyncParent actor dies.
 class VsyncChild MOZ_FINAL : public PVsyncChild
 {
+  NS_INLINE_DECL_REFCOUNTING(VsyncChild)
+
   friend class mozilla::ipc::BackgroundChildImpl;
 
 public:
   // Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag
   // mObservingVsync to handle the race problem of unobserving vsync event.
   bool SendObserve();
   bool SendUnobserve();
 
@@ -39,16 +42,17 @@ public:
 private:
   VsyncChild();
   virtual ~VsyncChild();
 
   virtual bool RecvNotify(const TimeStamp& aVsyncTimestamp) MOZ_OVERRIDE;
   virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) MOZ_OVERRIDE;
 
   bool mObservingVsync;
+  bool mIsShutdown;
 
   // The content side vsync observer.
   nsRefPtr<VsyncObserver> mObserver;
 };
 
 } // namespace layout
 } // namespatce mozilla