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 237092 a7b710c75a02b7f3620bab92d86ee7b0e52e24cf
parent 237091 cf2fb09e09b6f0b61efb430629d6a58a0e7edaa8
child 237093 dc35109e04d456fed6acb2691206e397e7aceea2
push id57871
push usermwoodrow@mozilla.com
push dateWed, 01 Apr 2015 22:10:44 +0000
treeherdermozilla-inbound@a7b710c75a02 [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();