|
|
Created:
3 years, 9 months ago by Alexander Semashko Modified:
3 years, 9 months ago CC:
chromium-reviews, blink-reviews, mlamouri+watch-blink_chromium.org, kinuko+watch, blink-reviews-bindings_chromium.org, dcheng, haraken Target Ref:
refs/pending/heads/master Project:
chromium Visibility:
Public. |
DescriptionMake context initialization order deterministic in WebFrame::swap().
DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds
with DCHECKs turned off this issue manifests with "Type Error: no
access" errors in console and scripts not working.
Started happening approx. in M56.
Repro steps:
1. Install several extensions;
2. Visit a number of pages in a tab;
3. Do a lot of back and forward navigations quickly (not waiting till
pages load).
This is caused by setting the global object in WindowProxy after it was
initialized. This happens when WindowProxyManagerBase::setGlobals
processes a non-main world first. It sends out a didCreateScriptContext
call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether
it is the main world script context, and compares with
WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world
script context is initialized. At this point the call stack is like this:
1 blink::LocalWindowProxy::initialize
2 blink::ScriptController::windowProxy
3 blink::toV8Context
4 blink::ScriptState::forMainWorld
5 blink::WebLocalFrameImpl::mainWorldScriptContext
6 extensions::ExtensionFrameHelper::DidCreateScriptContext
7 content::RenderFrameImpl::didCreateScriptContext
8 blink::LocalWindowProxy::initialize
9 blink::WindowProxy::setGlobal
10 blink::WindowProxyManagerBase::setGlobals
11 blink::WebFrame::swap
12 content::RenderFrameImpl::SwapIn
13 content::RenderFrameImpl::didCommitProvisionalLoad
14 blink::FrameLoaderClientImpl::dispatchDidCommitLoad
15 blink::FrameLoader::receivedFirstData
16 blink::DocumentLoader::createWriterFor
17 blink::DocumentLoader::ensureWriter
18 blink::DocumentLoader::commitData
After that WindowProxyManagerBase::setGlobals continues its work and
sets the global object for the main world WindowProxy, and it becomes
broken.
BUG=700077
Review-Url: https://codereview.chromium.org/2743653002
Cr-Commit-Position: refs/heads/master@{#455951}
Committed: https://chromium.googlesource.com/chromium/src/+/1993f6e8c0fe533f411ae5764231072e212221ad
Patch Set 1 #
Total comments: 3
Patch Set 2 : Add comment. #
Messages
Total messages: 32 (17 generated)
The CQ bit was checked by ahest@yandex-team.ru to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
Description was changed from ========== Patch issue with m_globalProxy != context()->Global(). BUG= ========== to ========== Fix a source of DCHECK(m_globalProxy != context()->Global()) failures in WindowProxy::globalIfNotDetached. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: http://pastebin.com/SgXx3841. After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. This is probably related to https://crbug.com/696528 and/or https://crbug.com/696577 (these bugs are mentioned in https://chromiumcodereview.appspot.com/2626183003/ and https://codereview.chromium.org/2724573002; don't know what's in them since these bugs are restricted). BUG= ==========
Description was changed from ========== Fix a source of DCHECK(m_globalProxy != context()->Global()) failures in WindowProxy::globalIfNotDetached. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: http://pastebin.com/SgXx3841. After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. This is probably related to https://crbug.com/696528 and/or https://crbug.com/696577 (these bugs are mentioned in https://chromiumcodereview.appspot.com/2626183003/ and https://codereview.chromium.org/2724573002; don't know what's in them since these bugs are restricted). BUG= ========== to ========== Fix a source of DCHECK failures in WindowProxy::globalIfNotDetached. DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: http://pastebin.com/SgXx3841. After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. Did not (yet) file a bug because this is probably related to https://crbug.com/696528 and/or https://crbug.com/696577 (these bugs are mentioned in https://chromiumcodereview.appspot.com/2626183003/ and https://codereview.chromium.org/2724573002; don't know what's in them since these bugs are restricted). ==========
ahest@yandex-team.ru changed reviewers: + dcheng@chromium.org, yukishiino@chromium.org
PTAL I think that something is missing here. Something like a [D]CHECK in WindowProxy::setGlobal that asserts that the context in not initialized yet. But I'm not sure that there are no valid cases when that condition does not hold true.
Thanks for reproing it locally. I suspected this to be the cause of the bug in https://codereview.chromium.org/2737553007/#msg8, based on the crashes that we were seeing. However, I don't see how this CL addresses that?
Oh never mind, it's because we made the ordering deterministic.
Description was changed from ========== Fix a source of DCHECK failures in WindowProxy::globalIfNotDetached. DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: http://pastebin.com/SgXx3841. After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. Did not (yet) file a bug because this is probably related to https://crbug.com/696528 and/or https://crbug.com/696577 (these bugs are mentioned in https://chromiumcodereview.appspot.com/2626183003/ and https://codereview.chromium.org/2724573002; don't know what's in them since these bugs are restricted). ========== to ========== Fix a source of DCHECK failures in WindowProxy::globalIfNotDetached. DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: http://pastebin.com/SgXx3841. After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 ==========
LGTM, but with some nits for the CL description. For the CL subject / first line of the description, please change it to: Make context initialization order deterministic in WebFrame::swap(). For the stack trace, please inline it from pastebin and trim it to just the function names. I agree that we want a [D]CHECK here (and my plan was to add one after I figured out what was going wrong), but we should do it in a separate CL, in case there are any other edge cases we missed.
Description was changed from ========== Fix a source of DCHECK failures in WindowProxy::globalIfNotDetached. DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: http://pastebin.com/SgXx3841. After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 ========== to ========== Make context initialization order deterministic in WebFrame::swap(). DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: 1 blink::LocalWindowProxy::initialize 2 blink::ScriptController::windowProxy 3 blink::toV8Context 4 blink::ScriptState::forMainWorld 5 blink::WebLocalFrameImpl::mainWorldScriptContext 6 extensions::ExtensionFrameHelper::DidCreateScriptContext 7 content::RenderFrameImpl::didCreateScriptContext 8 blink::LocalWindowProxy::initialize 9 blink::WindowProxy::setGlobal 10 blink::WindowProxyManagerBase::setGlobals 11 blink::WebFrame::swap 12 content::RenderFrameImpl::SwapIn 13 content::RenderFrameImpl::didCommitProvisionalLoad 14 blink::FrameLoaderClientImpl::dispatchDidCommitLoad 15 blink::FrameLoader::receivedFirstData 16 blink::DocumentLoader::createWriterFor 17 blink::DocumentLoader::ensureWriter 18 blink::DocumentLoader::commitData After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 ==========
Description was changed from ========== Make context initialization order deterministic in WebFrame::swap(). DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: 1 blink::LocalWindowProxy::initialize 2 blink::ScriptController::windowProxy 3 blink::toV8Context 4 blink::ScriptState::forMainWorld 5 blink::WebLocalFrameImpl::mainWorldScriptContext 6 extensions::ExtensionFrameHelper::DidCreateScriptContext 7 content::RenderFrameImpl::didCreateScriptContext 8 blink::LocalWindowProxy::initialize 9 blink::WindowProxy::setGlobal 10 blink::WindowProxyManagerBase::setGlobals 11 blink::WebFrame::swap 12 content::RenderFrameImpl::SwapIn 13 content::RenderFrameImpl::didCommitProvisionalLoad 14 blink::FrameLoaderClientImpl::dispatchDidCommitLoad 15 blink::FrameLoader::receivedFirstData 16 blink::DocumentLoader::createWriterFor 17 blink::DocumentLoader::ensureWriter 18 blink::DocumentLoader::commitData After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 ========== to ========== Make context initialization order deterministic in WebFrame::swap(). DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: 1 blink::LocalWindowProxy::initialize 2 blink::ScriptController::windowProxy 3 blink::toV8Context 4 blink::ScriptState::forMainWorld 5 blink::WebLocalFrameImpl::mainWorldScriptContext 6 extensions::ExtensionFrameHelper::DidCreateScriptContext 7 content::RenderFrameImpl::didCreateScriptContext 8 blink::LocalWindowProxy::initialize 9 blink::WindowProxy::setGlobal 10 blink::WindowProxyManagerBase::setGlobals 11 blink::WebFrame::swap 12 content::RenderFrameImpl::SwapIn 13 content::RenderFrameImpl::didCommitProvisionalLoad 14 blink::FrameLoaderClientImpl::dispatchDidCommitLoad 15 blink::FrameLoader::receivedFirstData 16 blink::DocumentLoader::createWriterFor 17 blink::DocumentLoader::ensureWriter 18 blink::DocumentLoader::commitData After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 ==========
On 2017/03/09 19:09:56, dcheng wrote: > LGTM, but with some nits for the CL description. > > For the CL subject / first line of the description, please change it to: > Make context initialization order deterministic in WebFrame::swap(). > > For the stack trace, please inline it from pastebin and trim it to just the > function names. > > I agree that we want a [D]CHECK here (and my plan was to add one after I figured > out what was going wrong), but we should do it in a separate CL, in case there > are any other edge cases we missed. Ok. I updated the description.
The CQ bit was checked by ahest@yandex-team.ru
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: chromium_presubmit on master.tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/chromium_presub...)
haraken@chromium.org changed reviewers: + haraken@chromium.org
LGTM https://codereview.chromium.org/2743653002/diff/1/third_party/WebKit/Source/b... File third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h (right): https://codereview.chromium.org/2743653002/diff/1/third_party/WebKit/Source/b... third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h:34: Vector<std::pair<DOMWrapperWorld*, v8::Local<v8::Object>>>; Would you add a comment and explain why this needs to be a vector?
https://codereview.chromium.org/2743653002/diff/1/third_party/WebKit/Source/b... File third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h (right): https://codereview.chromium.org/2743653002/diff/1/third_party/WebKit/Source/b... third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h:34: Vector<std::pair<DOMWrapperWorld*, v8::Local<v8::Object>>>; On 2017/03/09 22:04:46, haraken wrote: > > Would you add a comment and explain why this needs to be a vector? I thought about asking for a comment, but it felt like a very fragile comment: if something in the embedder changes and it starts getting an isolated world context *while* initializing the main context, we'll have similar issues. So this is kind of a bandaid fix while the extensions code is fixed (but is still useful to have, because deterministic initialization seems like a good thing).
https://codereview.chromium.org/2743653002/diff/1/third_party/WebKit/Source/b... File third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h (right): https://codereview.chromium.org/2743653002/diff/1/third_party/WebKit/Source/b... third_party/WebKit/Source/bindings/core/v8/WindowProxyManager.h:34: Vector<std::pair<DOMWrapperWorld*, v8::Local<v8::Object>>>; On 2017/03/09 22:10:20, dcheng wrote: > On 2017/03/09 22:04:46, haraken wrote: > > > > Would you add a comment and explain why this needs to be a vector? > > I thought about asking for a comment, but it felt like a very fragile comment: > if something in the embedder changes and it starts getting an isolated world > context *while* initializing the main context, we'll have similar issues. So > this is kind of a bandaid fix while the extensions code is fixed (but is still > useful to have, because deterministic initialization seems like a good thing). Added a comment. Is it ok?
Comment LGTM
The CQ bit was checked by ahest@yandex-team.ru
The patchset sent to the CQ was uploaded after l-g-t-m from haraken@chromium.org Link to the patchset: https://codereview.chromium.org/2743653002/#ps20001 (title: "Add comment.")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
CQ is committing da patch. Bot data: {"patchset_id": 20001, "attempt_start_ts": 1489098764952720, "parent_rev": "062a43cf645faf5a158afa6657bb85b6a5ebd6a8", "commit_rev": "1993f6e8c0fe533f411ae5764231072e212221ad"}
Message was sent while issue was closed.
Description was changed from ========== Make context initialization order deterministic in WebFrame::swap(). DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: 1 blink::LocalWindowProxy::initialize 2 blink::ScriptController::windowProxy 3 blink::toV8Context 4 blink::ScriptState::forMainWorld 5 blink::WebLocalFrameImpl::mainWorldScriptContext 6 extensions::ExtensionFrameHelper::DidCreateScriptContext 7 content::RenderFrameImpl::didCreateScriptContext 8 blink::LocalWindowProxy::initialize 9 blink::WindowProxy::setGlobal 10 blink::WindowProxyManagerBase::setGlobals 11 blink::WebFrame::swap 12 content::RenderFrameImpl::SwapIn 13 content::RenderFrameImpl::didCommitProvisionalLoad 14 blink::FrameLoaderClientImpl::dispatchDidCommitLoad 15 blink::FrameLoader::receivedFirstData 16 blink::DocumentLoader::createWriterFor 17 blink::DocumentLoader::ensureWriter 18 blink::DocumentLoader::commitData After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 ========== to ========== Make context initialization order deterministic in WebFrame::swap(). DCHECK(m_globalProxy != context()->Global()) sometimes fail. In builds with DCHECKs turned off this issue manifests with "Type Error: no access" errors in console and scripts not working. Started happening approx. in M56. Repro steps: 1. Install several extensions; 2. Visit a number of pages in a tab; 3. Do a lot of back and forward navigations quickly (not waiting till pages load). This is caused by setting the global object in WindowProxy after it was initialized. This happens when WindowProxyManagerBase::setGlobals processes a non-main world first. It sends out a didCreateScriptContext call. ExtensionFrameHelper::DidCreateScriptContext wants to know whether it is the main world script context, and compares with WebLocalFrameImpl::mainWorldScriptContext(). As a result, main world script context is initialized. At this point the call stack is like this: 1 blink::LocalWindowProxy::initialize 2 blink::ScriptController::windowProxy 3 blink::toV8Context 4 blink::ScriptState::forMainWorld 5 blink::WebLocalFrameImpl::mainWorldScriptContext 6 extensions::ExtensionFrameHelper::DidCreateScriptContext 7 content::RenderFrameImpl::didCreateScriptContext 8 blink::LocalWindowProxy::initialize 9 blink::WindowProxy::setGlobal 10 blink::WindowProxyManagerBase::setGlobals 11 blink::WebFrame::swap 12 content::RenderFrameImpl::SwapIn 13 content::RenderFrameImpl::didCommitProvisionalLoad 14 blink::FrameLoaderClientImpl::dispatchDidCommitLoad 15 blink::FrameLoader::receivedFirstData 16 blink::DocumentLoader::createWriterFor 17 blink::DocumentLoader::ensureWriter 18 blink::DocumentLoader::commitData After that WindowProxyManagerBase::setGlobals continues its work and sets the global object for the main world WindowProxy, and it becomes broken. BUG=700077 Review-Url: https://codereview.chromium.org/2743653002 Cr-Commit-Position: refs/heads/master@{#455951} Committed: https://chromium.googlesource.com/chromium/src/+/1993f6e8c0fe533f411ae5764231... ==========
Message was sent while issue was closed.
Committed patchset #2 (id:20001) as https://chromium.googlesource.com/chromium/src/+/1993f6e8c0fe533f411ae5764231...
Message was sent while issue was closed.
LGTM! This is a great catch!! |