Commit db71a0af authored by Raymond Toy's avatar Raymond Toy Committed by Commit Bot

Clear context from orphan handlers when BaseAudioContext is going away

When preparing to collect a BaseAudioContext, go through all the
rendering_orphan_handlers_ and deletable_orphan_handlers_ and remove
the context from the handler.  This ensures that these handlers no
longer have references to the context when the BaseAudioContext is
destroyed because in some cases, these orphan handlers will get pulled
and access the context, which is already gone.

Clearing these in a prefinalizer ensures these orphan handlers don't
try to touch the context.

Manually verified that the repro case no longer reproduces.

Bug: 1062247
Change-Id: I50d083743903eb9544e09aa1ee912fc880331501
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107806Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarHongchan Choi <hongchan@chromium.org>
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751814}
parent 100d0be8
......@@ -178,6 +178,12 @@ void BaseAudioContext::Uninitialize() {
DCHECK_EQ(resume_resolvers_.size(), 0u);
}
void BaseAudioContext::Dispose() {
// BaseAudioContext is going away, so remove the context from the orphan
// handlers.
GetDeferredTaskHandler().ClearContextFromOrphanHandlers();
}
void BaseAudioContext::ContextLifecycleStateChanged(
mojom::FrameLifecycleState state) {
// Don't need to do anything for an offline context.
......
......@@ -96,6 +96,7 @@ class MODULES_EXPORT BaseAudioContext
public InspectorHelperMixin {
USING_GARBAGE_COLLECTED_MIXIN(BaseAudioContext);
DEFINE_WRAPPERTYPEINFO();
USING_PRE_FINALIZER(BaseAudioContext, Dispose);
public:
// The state of an audio context. On creation, the state is Suspended. The
......@@ -115,6 +116,8 @@ class MODULES_EXPORT BaseAudioContext
return dest ? dest->GetAudioDestinationHandler().IsInitialized() : false;
}
void Dispose();
// Document notification
void ContextLifecycleStateChanged(mojom::FrameLifecycleState) override;
void ContextDestroyed() override;
......
......@@ -302,10 +302,7 @@ void DeferredTaskHandler::HandleDeferredTasks() {
}
void DeferredTaskHandler::ContextWillBeDestroyed() {
for (auto& handler : rendering_orphan_handlers_)
handler->ClearContext();
for (auto& handler : deletable_orphan_handlers_)
handler->ClearContext();
ClearContextFromOrphanHandlers();
ClearHandlersToBeDeleted();
// Some handlers might live because of their cross thread tasks.
}
......@@ -374,6 +371,19 @@ void DeferredTaskHandler::ClearHandlersToBeDeleted() {
active_source_handlers_.clear();
}
void DeferredTaskHandler::ClearContextFromOrphanHandlers() {
DCHECK(IsMainThread());
// |rendering_orphan_handlers_| and |deletable_orphan_handlers_| can
// be modified on the audio thread.
GraphAutoLocker locker(*this);
for (auto& handler : rendering_orphan_handlers_)
handler->ClearContext();
for (auto& handler : deletable_orphan_handlers_)
handler->ClearContext();
}
void DeferredTaskHandler::SetAudioThreadToCurrentThread() {
DCHECK(!IsMainThread());
audio_thread_.store(CurrentThread(), std::memory_order_relaxed);
......
......@@ -111,6 +111,9 @@ class MODULES_EXPORT DeferredTaskHandler final
void RequestToDeleteHandlersOnMainThread();
void ClearHandlersToBeDeleted();
// Clear the context from the rendering and deletable orphan handlers.
void ClearContextFromOrphanHandlers();
bool AcceptsTailProcessing() const { return accepts_tail_processing_; }
void StopAcceptingTailProcessing() { accepts_tail_processing_ = false; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment