Bug 1102612 - Don't attempt to read data from a resource if we've evicted the start position. r=jya, a=sledru
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 02 Apr 2015 11:10:34 +1300
changeset 258320 98ac0c020205
parent 258319 589aafc2bb13
child 258321 8ff6cc64abe8
push id4645
push userryanvm@gmail.com
push date2015-04-07 15:05 +0000
treeherdermozilla-beta@8f0271f2c153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, sledru
bugs1102612
milestone38.0
Bug 1102612 - Don't attempt to read data from a resource if we've evicted the start position. r=jya, a=sledru
dom/media/mediasource/ResourceQueue.h
dom/media/mediasource/SourceBufferResource.cpp
--- a/dom/media/mediasource/ResourceQueue.h
+++ b/dom/media/mediasource/ResourceQueue.h
@@ -181,17 +181,17 @@ private:
   }
 
   // Returns the index of the resource that contains the given
   // logical offset. aResourceOffset will contain the offset into
   // the resource at the given index returned if it is not null.  If
   // no such resource exists, returns GetSize() and aOffset is
   // untouched.
   uint32_t GetAtOffset(uint64_t aOffset, uint32_t *aResourceOffset) {
-    MOZ_ASSERT(aOffset >= mOffset);
+    MOZ_RELEASE_ASSERT(aOffset >= mOffset);
     uint64_t offset = mOffset;
     for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
       ResourceItem* item = ResourceAt(i);
       // If the item contains the start of the offset we want to
       // break out of the loop.
       if (item->mData->Length() + offset > aOffset) {
         if (aResourceOffset) {
           *aResourceOffset = aOffset - offset;
--- a/dom/media/mediasource/SourceBufferResource.cpp
+++ b/dom/media/mediasource/SourceBufferResource.cpp
@@ -64,16 +64,21 @@ SourceBufferResource::ReadInternal(char*
   // sanely. :-(
   uint64_t readOffset = mOffset;
 
   while (aMayBlock &&
          !mEnded &&
          readOffset + aCount > static_cast<uint64_t>(GetLength())) {
     SBR_DEBUGV("waiting for data");
     mMonitor.Wait();
+    // The callers of this function should have checked this, but it's
+    // possible that we had an eviction while waiting on the monitor.
+    if (readOffset < mInputBuffer.GetOffset()) {
+      return NS_ERROR_FAILURE;
+    }
   }
 
   uint32_t available = GetLength() - readOffset;
   uint32_t count = std::min(aCount, available);
   SBR_DEBUGV("readOffset=%llu GetLength()=%u available=%u count=%u mEnded=%d",
              this, readOffset, GetLength(), available, count, mEnded);
   if (available == 0) {
     SBR_DEBUGV("reached EOF");
@@ -174,28 +179,37 @@ SourceBufferResource::ReadFromCache(char
 }
 
 uint32_t
 SourceBufferResource::EvictData(uint64_t aPlaybackOffset, uint32_t aThreshold)
 {
   SBR_DEBUG("EvictData(aPlaybackOffset=%llu,"
             "aThreshold=%u)", aPlaybackOffset, aThreshold);
   ReentrantMonitorAutoEnter mon(mMonitor);
-  return mInputBuffer.Evict(aPlaybackOffset, aThreshold);
+  uint32_t result = mInputBuffer.Evict(aPlaybackOffset, aThreshold);
+  if (result > 0) {
+    // Wake up any waiting threads in case a ReadInternal call
+    // is now invalid.
+    mon.NotifyAll();
+  }
+  return result;
 }
 
 void
 SourceBufferResource::EvictBefore(uint64_t aOffset)
 {
   SBR_DEBUG("EvictBefore(aOffset=%llu)", aOffset);
   ReentrantMonitorAutoEnter mon(mMonitor);
   // If aOffset is past the current playback offset we don't evict.
   if (aOffset < mOffset) {
     mInputBuffer.EvictBefore(aOffset);
   }
+  // Wake up any waiting threads in case a ReadInternal call
+  // is now invalid.
+  mon.NotifyAll();
 }
 
 uint32_t
 SourceBufferResource::EvictAll()
 {
   SBR_DEBUG("EvictAll()");
   ReentrantMonitorAutoEnter mon(mMonitor);
   return mInputBuffer.EvictAll();