Bug 1395017. P3 - always dispatch a task to run UpdatePrincipal() even when CacheClientUpdatePrincipal() already runs in the main thread.
When MediaCacheStream::NotifyDataReceived() runs off the main thread,
there is no guarantee that the principal will be updated before the new
data is observable to the consumer because the principal can only be
updated on the main thread while the consumer can access the data off
the main thread.
To make the code simpler, we always dispatch a task to run UpdatePrincipal()
even when CacheClientUpdatePrincipal() already runs in the main thread.
This also avoid the deadlock because ChannelMediaResource::UpdatePrincipal()
will never run with the cache monitor held.
MozReview-Commit-ID: 9CdrJnaV0hl
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1879,29 +1879,26 @@ MediaCacheStream::UpdatePrincipal(nsIPri
}
void
MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData)
{
// This might happen off the main thread.
MOZ_DIAGNOSTIC_ASSERT(!mClosed);
- // Update principals before putting the data in the cache. This is important,
- // we want to make sure all principals are updated before any consumer
- // can see the new data.
- // We do this without holding the cache monitor, in case the client wants
- // to do something that takes a lock.
+ ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
{
+ // Need to acquire the monitor because this code might run
+ // off the main thread.
MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
while (MediaCacheStream* stream = iter.Next()) {
stream->mClient->CacheClientUpdatePrincipal();
}
}
- ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
int64_t size = aSize;
const char* data = aData;
LOG("Stream %p DataReceived at %" PRId64 " count=%" PRId64,
this, mChannelOffset, aSize);
// We process the data one block (or part of a block) at a time
while (size > 0) {
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -884,22 +884,16 @@ ChannelMediaResource::UpdatePrincipal()
if (mCacheStream.UpdatePrincipal(principal)) {
mCallback->NotifyPrincipalChanged();
}
}
void
ChannelMediaResource::CacheClientUpdatePrincipal()
{
- // This might happen off the main thread.
- if (NS_IsMainThread()) {
- UpdatePrincipal();
- return;
- }
-
SystemGroup::Dispatch(
TaskCategory::Other,
NewRunnableMethod("ChannelMediaResource::UpdatePrincipal",
this,
&ChannelMediaResource::UpdatePrincipal));
}
void