Bug 1102612 - Don't attempt to read data from a resource if we've evicted the start position. r=jya
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 02 Apr 2015 11:10:34 +1300
changeset 237194 a7b710c75a02
parent 237193 cf2fb09e09b6
child 237195 dc35109e04d4
push id28529
push usercbook@mozilla.com
push dateThu, 02 Apr 2015 12:09:53 +0000
treeherdermozilla-central@35046df9df1f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1102612
milestone40.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 1102612 - Don't attempt to read data from a resource if we've evicted the start position. r=jya
dom/media/mediasource/ResourceQueue.h
dom/media/mediasource/SourceBufferResource.cpp
--- a/dom/media/mediasource/ResourceQueue.h
+++ b/dom/media/mediasource/ResourceQueue.h
@@ -191,17 +191,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",
              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();