Bug 1268169 - Don't touch a ShmemSection's memory after shutdown. r=kats a=ritu
authorNicolas Silva <nsilva@mozilla.com>
Wed, 04 May 2016 13:36:48 +0200
changeset 332815 ba62a7d1c20dbf3d06ead5912b0d0f689bb79000
parent 332814 7d65f322abdbd49af0b4b12267de5123b672b4ff
child 332816 261915e8601067a49679353ccb9cd601bd8a619c
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, ritu
bugs1268169
milestone48.0a2
Bug 1268169 - Don't touch a ShmemSection's memory after shutdown. r=kats a=ritu
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -203,49 +203,54 @@ struct AutoTxnEnd {
 // XXX - We should actually figure out the minimum shmem allocation size on
 // a certain platform and use that.
 const uint32_t sShmemPageSize = 4096;
 
 #ifdef DEBUG
 const uint32_t sSupportedBlockSize = 4;
 #endif
 
-FixedSizeSmallShmemSectionAllocator::FixedSizeSmallShmemSectionAllocator(ShmemAllocator* aShmProvider)
+FixedSizeSmallShmemSectionAllocator::FixedSizeSmallShmemSectionAllocator(ClientIPCAllocator* aShmProvider)
 : mShmProvider(aShmProvider)
 {
-  MOZ_ASSERT(mShmProvider);
+  MOZ_ASSERT(mShmProvider && mShmProvider->AsShmemAllocator());
 }
 
 FixedSizeSmallShmemSectionAllocator::~FixedSizeSmallShmemSectionAllocator()
 {
   ShrinkShmemSectionHeap();
 }
 
 bool
 FixedSizeSmallShmemSectionAllocator::AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection)
 {
   // For now we only support sizes of 4. If we want to support different sizes
   // some more complicated bookkeeping should be added.
   MOZ_ASSERT(aSize == sSupportedBlockSize);
   MOZ_ASSERT(aShmemSection);
 
+  if (!IPCOpen()) {
+    gfxCriticalError() << "Attempt to allocate a ShmemSection after shutdown.";
+    return false;
+  }
+
   uint32_t allocationSize = (aSize + sizeof(ShmemSectionHeapAllocation));
 
   for (size_t i = 0; i < mUsedShmems.size(); i++) {
     ShmemSectionHeapHeader* header = mUsedShmems[i].get<ShmemSectionHeapHeader>();
     if ((header->mAllocatedBlocks + 1) * allocationSize + sizeof(ShmemSectionHeapHeader) < sShmemPageSize) {
       aShmemSection->shmem() = mUsedShmems[i];
       MOZ_ASSERT(mUsedShmems[i].IsWritable());
       break;
     }
   }
 
   if (!aShmemSection->shmem().IsWritable()) {
     ipc::Shmem tmp;
-    if (!mShmProvider->AllocUnsafeShmem(sShmemPageSize, OptimalShmemType(), &tmp)) {
+    if (!GetShmAllocator()->AllocUnsafeShmem(sShmemPageSize, OptimalShmemType(), &tmp)) {
       return false;
     }
 
     ShmemSectionHeapHeader* header = tmp.get<ShmemSectionHeapHeader>();
     header->mTotalBlocks = 0;
     header->mAllocatedBlocks = 0;
 
     mUsedShmems.push_back(tmp);
@@ -290,16 +295,20 @@ FixedSizeSmallShmemSectionAllocator::All
 }
 
 void
 FixedSizeSmallShmemSectionAllocator::FreeShmemSection(mozilla::layers::ShmemSection& aShmemSection)
 {
   MOZ_ASSERT(aShmemSection.size() == sSupportedBlockSize);
   MOZ_ASSERT(aShmemSection.offset() < sShmemPageSize - sSupportedBlockSize);
 
+  if (!aShmemSection.shmem().IsWritable()) {
+    return;
+  }
+
   ShmemSectionHeapAllocation* allocHeader =
     reinterpret_cast<ShmemSectionHeapAllocation*>(aShmemSection.shmem().get<char>() +
                                                   aShmemSection.offset() -
                                                   sizeof(ShmemSectionHeapAllocation));
 
   MOZ_ASSERT(allocHeader->mSize == aShmemSection.size());
 
   DebugOnly<bool> success = allocHeader->mStatus.compareExchange(STATUS_ALLOCATED, STATUS_FREED);
@@ -308,32 +317,41 @@ FixedSizeSmallShmemSectionAllocator::Fre
 
   ShmemSectionHeapHeader* header = aShmemSection.shmem().get<ShmemSectionHeapHeader>();
   header->mAllocatedBlocks--;
 }
 
 void
 FixedSizeSmallShmemSectionAllocator::DeallocShmemSection(mozilla::layers::ShmemSection& aShmemSection)
 {
+  if (!IPCOpen()) {
+    gfxCriticalNote << "Attempt to dealloc a ShmemSections after shutdown.";
+    return;
+  }
+
   FreeShmemSection(aShmemSection);
   ShrinkShmemSectionHeap();
 }
 
 
 void
 FixedSizeSmallShmemSectionAllocator::ShrinkShmemSectionHeap()
 {
+  if (!IPCOpen()) {
+    mUsedShmems.clear();
+    return;
+  }
+
   // The loop will terminate as we either increase i, or decrease size
   // every time through.
   size_t i = 0;
   while (i < mUsedShmems.size()) {
     ShmemSectionHeapHeader* header = mUsedShmems[i].get<ShmemSectionHeapHeader>();
     if (header->mAllocatedBlocks == 0) {
-      mShmProvider->DeallocShmem(mUsedShmems[i]);
-
+      GetShmAllocator()->DeallocShmem(mUsedShmems[i]);
       // We don't particularly care about order, move the last one in the array
       // to this position.
       if (i < mUsedShmems.size() - 1) {
         mUsedShmems[i] = mUsedShmems[mUsedShmems.size() - 1];
       }
       mUsedShmems.pop_back();
     } else {
       i++;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -459,32 +459,36 @@ public:
   };
 
   struct ShmemSectionHeapAllocation
   {
     Atomic<uint32_t> mStatus;
     uint32_t mSize;
   };
 
-  explicit FixedSizeSmallShmemSectionAllocator(ShmemAllocator* aShmProvider);
+  explicit FixedSizeSmallShmemSectionAllocator(ClientIPCAllocator* aShmProvider);
 
   ~FixedSizeSmallShmemSectionAllocator();
 
   virtual bool AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) override;
 
   virtual void DeallocShmemSection(ShmemSection& aShmemSection) override;
 
   virtual void MemoryPressure() override { ShrinkShmemSectionHeap(); }
 
   // can be called on the compositor process.
   static void FreeShmemSection(ShmemSection& aShmemSection);
 
   void ShrinkShmemSectionHeap();
 
+  ShmemAllocator* GetShmAllocator() { return mShmProvider->AsShmemAllocator(); }
+
+  bool IPCOpen() const { return mShmProvider->IPCOpen(); }
+
 protected:
   std::vector<mozilla::ipc::Shmem> mUsedShmems;
-  ShmemAllocator* mShmProvider;
+  ClientIPCAllocator* mShmProvider;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // ifndef mozilla_layers_ShadowLayers_h