New issue
Advanced search Search tips

Issue 853390 link

Starred by 4 users

Issue metadata

Status: Started
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

EME Promises not cleaned up properly

Project Member Reported by jrumm...@chromium.org, Jun 15 2018

Issue description

In b/110072353 a user reported a crash on Android when an app that uses encrypted media takes a long time to start up and they swiped it away as it took too long. The crash reported:

[12528:12544:FATAL:ScriptPromiseResolver.h(57)] Check failed: state_ == kDetached || !is_promise_called_ || !GetScriptState()->ContextIsValid() || !GetExecutionContext() || GetExecutionContext()->IsContextDestroyed(). 

The current code in media:: has checks to make sure that the promise is fulfilled. However, once the blink:: promise is created, for many actions they are added to a queue that calls the media:: code later. So maybe some promise was created, but it is sitting in a queue. The app is torn down, and the items in the queue are simply destroyed. That could cause the ScriptPromiseResolver to get destroyed without ever being fulfilled.

To test this out, I tried running the layout test encrypted-media-async-creation-with-gc.html after commenting out the handling of the timer queue. Get the same crash:

[1:1:0615/154731.693041:FATAL:script_promise_resolver.h(57)] Check failed: state_ == kDetached || !is_promise_called_ || !GetScriptState()->ContextIsValid() || !GetExecutionContext() || GetExecutionContext()->IsContextDestroyed(). 
#0 0x7f3a68fd5a3d base::debug::StackTrace::StackTrace()
#1 0x7f3a68d1f4bc base::debug::StackTrace::StackTrace()
#2 0x7f3a68d8e51a logging::LogMessage::~LogMessage()
#3 0x7f3a57fe7941 blink::ScriptPromiseResolver::~ScriptPromiseResolver()
#4 0x7f3a54735544 blink::GarbageCollectedFinalized<>::FinalizeGarbageCollectedObject()
#5 0x7f3a54735515 blink::FinalizerTraitImpl<>::Finalize()
#6 0x7f3a547354f5 blink::FinalizerTrait<>::Finalize()
#7 0x7f3a561f9f9e blink::HeapObjectHeader::Finalize()
#8 0x7f3a562010b8 blink::NormalPage::Sweep()

Will fix up the code so if the queue is destroyed while there are pending promises, the promises are rejected.

 

Comment 1 by yucliu@chromium.org, Jun 15 2018

Thanks for this! Please let me know if I can do any help!
More complicated than I thought. Can't simply update the destructor, as then the compiler complains with:

media_key_session.cc:200:5: error: [blink-gc] Finalizer '~PendingAction' accesses potentially finalized field 'result_'.
    result_->CompleteWithError(kWebContentDecryptionModuleExceptionInvalidStateError, 0, "Operation aborted.");
    ^
media_key_session.cc:221:3: note: [blink-gc] Potentially finalized field 'result_' declared here:
  Member<ContentDecryptionModuleResult> result_;

So I have to use a prefinalizer.

Using a prefinalizer fails, as rejecting the promise creates a DomException, which is not allowed during gc.

[1:1:0615/170254.300828:FATAL:v8_per_isolate_data.cc(52)] Check failed: !ScriptForbiddenScope::IsScriptForbidden(). 
#11 0x7f0dd54dc21b blink::ToV8()
#12 0x7f0dd557140f blink::V8ThrowDOMException::CreateDOMException()
#13 0x7f0dd1dafece blink::ContentDecryptionModuleResultPromise::Reject()
#14 0x7f0dd1db02da blink::ContentDecryptionModuleResultPromise::CompleteWithError()
#15 0x7f0dd1dbc579 blink::MediaKeySession::PendingAction::Dispose()
#16 0x7f0dd1dbc4ec blink::MediaKeySession::PendingAction::InvokePreFinalizer()

There is ScriptPromiseResolver::Detach(), so that might work as the object is going away anyway. The alternative might be to create the DomException at construction time, but that seems a waste to create something that will likely never be used.
Seems like the bug is not related to CDM. We have other crash with similar stack trace but there's no CDM activity.

Sign in to add a comment