RESOLVED WONTFIX Bug 111074
REGRESSION(r141450): failed ASSERT in FrameView::scheduleRelayout()
https://bugs.webkit.org/show_bug.cgi?id=111074
Summary REGRESSION(r141450): failed ASSERT in FrameView::scheduleRelayout()
Alberto Garcia
Reported 2013-02-28 06:30:03 PST
I have a crash because of this failed assertion in FrameView::scheduleRelayout(): ASSERT(m_frame->view() == this) This seems to have been introduced in r141450, which was the fix for bug 107922. I cannot reproduce the crash after reverting that patch. The call to frameView->setUseFixedLayout(useFixedLayout) in Frame::createView() triggers a call to scheduleRelayout() while m_view is 0. Here's the backtrace: #0 WebCore::FrameView::scheduleRelayout (this=0x80a2d18) at /home/berto/devel/code/webkit/Source/WebCore/page/FrameView.cpp:2312 #1 0x7c8ec55a in WebCore::RenderObject::scheduleRelayout (this=0x8233890) at /home/berto/devel/code/webkit/Source/WebCore/rendering/RenderObject.cpp:2650 #2 0x7c8e46ce in WebCore::RenderObject::markContainingBlocksForLayout ( this=0x8233890, scheduleRelayout=true, newRoot=0x0) at /home/berto/devel/code/webkit/Source/WebCore/rendering/RenderObject.cpp:709 #3 0x78e2b104 in WebCore::RenderObject::setNeedsLayout (this=0x8233890, needsLayout=true, markParents=WebCore::MarkContainingBlockChain) at /home/berto/devel/code/webkit/Source/WebCore/rendering/RenderObject.h:1191 #4 0x7c626a1a in WebCore::FrameView::setNeedsLayout (this=0x82b8b88) at /home/berto/devel/code/webkit/Source/WebCore/page/FrameView.cpp:2439 #5 0x7c625b5e in WebCore::FrameView::contentsResized (this=0x82b8b88) at /home/berto/devel/code/webkit/Source/WebCore/page/FrameView.cpp:2122 #6 0x7c6b02ec in WebCore::ScrollView::setUseFixedLayout (this=0x82b8b88, enable=true) at /home/berto/devel/code/webkit/Source/WebCore/platform/ScrollView.cpp:324 #7 0x7c61875e in WebCore::Frame::createView (this=0x80a6f38, viewportSize=..., backgroundColor=..., transparent=false, fixedReportedSize=..., fixedLayoutSize=..., fixedVisibleContentRect=..., useFixedLayout=true, horizontalScrollbarMode=WebCore::ScrollbarAlwaysOff, horizontalLock=true, verticalScrollbarMode=WebCore::ScrollbarAlwaysOff, verticalLock=true) at /home/berto/devel/code/webkit/Source/WebCore/page/Frame.cpp:804 ...
Attachments
Patch (1.14 KB, patch)
2013-03-04 01:09 PST, Alberto Garcia
darin: review-
darin: commit-queue-
Alternative patch (13.68 KB, patch)
2013-03-13 12:31 PDT, Chris Dumez
simon.fraser: review-
another alternative (2.22 KB, patch)
2013-04-04 07:27 PDT, Mikhail Pozdnyakov
simon.fraser: review-
Alexandre Elias
Comment 1 2013-02-28 11:33:50 PST
Looks like the problem is the FrameView has not yet been attached to the Frame. Does it fix the problem if in Frame::createView, you move the three fixedLayout...() calls after setView(frameView)? That would be my proposed fix. By the way, what port is this?
Alberto Garcia
Comment 2 2013-03-01 03:17:37 PST
(In reply to comment #1) > Looks like the problem is the FrameView has not yet been attached to > the Frame. Does it fix the problem if in Frame::createView, you > move the three fixedLayout...() calls after setView(frameView)? > That would be my proposed fix. Hmmm... that doesn't seem to solve the problem. Now the new FrameView is attached to the frame, but during FrameView::setNeedsLayout() the renderView's setNeedsLayout() is also called. That ends up in RenderObject::scheduleRelayout(), the pointer to the FrameView there is different from the one we just created, so the assertion also fails. #0 0x7c826352 in WebCore::FrameView::scheduleRelayout (this=0x80a2c20) at /home/berto/devel/code/webkit/Source/WebCore/page/FrameView.cpp:2313 #1 0x7caec582 in WebCore::RenderObject::scheduleRelayout (this=0x8247360) at /home/berto/devel/code/webkit/Source/WebCore/rendering/RenderObject.cpp:2650 #2 0x7cae46f6 in WebCore::RenderObject::markContainingBlocksForLayout ( this=0x8247360, scheduleRelayout=true, newRoot=0x0) at /home/berto/devel/code/webkit/Source/WebCore/rendering/RenderObject.cpp:709 #3 0x7952b104 in WebCore::RenderObject::setNeedsLayout (this=0x8247360, needsLayout=true, markParents=WebCore::MarkContainingBlockChain) at /home/berto/devel/code/webkit/Source/WebCore/rendering/RenderObject.h:1191 #4 0x7c826a42 in WebCore::FrameView::setNeedsLayout (this=0x8468210) at /home/berto/devel/code/webkit/Source/WebCore/page/FrameView.cpp:2438 #5 0x7c825bae in WebCore::FrameView::contentsResized (this=0x8468210) at /home/berto/devel/code/webkit/Source/WebCore/page/FrameView.cpp:2124 #6 0x7c8b0314 in WebCore::ScrollView::setUseFixedLayout (this=0x8468210, enable=true) at /home/berto/devel/code/webkit/Source/WebCore/platform/ScrollView.cpp:324 #7 0x7c8187b4 in WebCore::Frame::createView (this=0x80a6cf0, viewportSize=..., backgroundColor=..., transparent=false, fixedReportedSize=..., fixedLayoutSize=..., fixedVisibleContentRect=..., useFixedLayout=true, horizontalScrollbarMode=WebCore::ScrollbarAlwaysOff, horizontalLock=true, verticalScrollbarMode=WebCore::ScrollbarAlwaysOff, verticalLock=true) at /home/berto/devel/code/webkit/Source/WebCore/page/Frame.cpp:808 #8 0x7955706c in WebCore::FrameLoaderClientBlackBerry::transitionToCommittedForNewPage (this=0x8091518) at /home/berto/devel/code/webkit/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.cpp:470 #9 0x7c74064c in WebCore::FrameLoader::transitionToCommitted (this=0x80a6d40, cachedPage=...) at /home/berto/devel/code/webkit/Source/WebCore/loader/FrameLoader.cpp:1893 > By the way, what port is this? BlackBerry
Alexandre Elias
Comment 3 2013-03-03 12:53:30 PST
So far I haven't been able to figure out via code inspection why the RenderView's frame may be different, so I'm not sure about the root cause. But to address this regression, one thing we can do is delete the "contentsResized();" call from "ScrollView::setUseFixedLayout()". I only need to keep the other one in "ScrollView::setFixedLayoutSize()". Could you check that fixes it?
Alexandre Elias
Comment 4 2013-03-03 13:06:24 PST
On second thought, before we do that, a better fix would be to add "if (!frame()->view()) return;" to "contentsResized()". I believe it should work if you move back the calls in Frame::createView() to their original place. Please give that a try.
Alberto Garcia
Comment 5 2013-03-04 01:09:25 PST
Created attachment 191168 [details] Patch (In reply to comment #4) > On second thought, before we do that, a better fix would be to add > "if (!frame()->view()) return;" to "contentsResized()". Hey, this seems to solve the problem, thanks!
James Robinson
Comment 6 2013-03-04 08:51:03 PST
Comment on attachment 191168 [details] Patch What's the testcase?
Xan Lopez
Comment 7 2013-03-04 23:29:03 PST
(In reply to comment #6) > (From update of attachment 191168 [details]) > What's the testcase? Maybe Alexandre can suggest what kind of test we could write for this particular regression.
Alexandre Elias
Comment 8 2013-03-04 23:41:58 PST
Seems impossible to test with a layout test given that it only happens in the Frame constructor with port-specific arguments. If Blackberry has a unit test system that runs on EWS, you can construct a Frame there, but AFAIK you don't, so I would be fine with submitting as is.
Darin Adler
Comment 9 2013-03-06 09:43:04 PST
Comment on attachment 191168 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=191168&action=review review- because this is too mysterious to do without a comment, and is probably not exactly the right fix > Source/WebCore/page/FrameView.cpp:2061 > + if (!frame()->view()) > + return; The strange thing about this is that we could add a check like this to all FrameView functions. We need a rule to tell us which ones need this. It’s particularly important because you are not contributing a test for this, so no one would be able to tell functions that need this kind of check from functions that don’t. Further, it’s non-obvious why taking a round trip to check for null is the right thing here. This needs a comment, not just the code, because it’s non-obvious. Further, maybe it should be a check for frame()->view() == this instead of frame()->view() being non-null. What’s special about contentsResized that means this is needed? Maybe the check belongs at the caller instead of inside this function?
Darin Adler
Comment 10 2013-03-06 09:43:26 PST
Comment on attachment 191168 [details] Patch A step in the right direction, but still needs work.
Alexandre Elias
Comment 11 2013-03-06 12:36:30 PST
There's a similar if() statement in FrameView::visibleContentsResized() for the same reason (ends up getting called from Frame::createView), with a comment. So this fix is at least consistent with what was there already (I agree it's somewhat strange though).
Alberto Garcia
Comment 12 2013-03-07 02:31:54 PST
(In reply to comment #9) > review- because this is too mysterious to do without a comment, and > is probably not exactly the right fix I think your objections are reasonable. If I find more information that can make us come up with a better fix I'll post it here. One thing to note, though, is that if I compile with assertions disabled then everything seems to work normally. Maybe that is a false assertion in FrameView::scheduleRelayout() ?
Simon Fraser (smfr)
Comment 13 2013-03-07 09:13:51 PST
I don't think it's a false assertion. It implies that something happened that is unexpected.
Chris Dumez
Comment 14 2013-03-13 08:32:48 PDT
FYI, The same assertion is easily reproduced in EFL's MiniBrowser if we use CacheModelPrimaryWebBrowser cache model. We currently don't get the assertion with CacheModelDocumentViewer cache model.
Chris Dumez
Comment 15 2013-03-13 12:31:07 PDT
Created attachment 192962 [details] Alternative patch This patch fixes the assertion hit for me.
Alexandre Elias
Comment 16 2013-03-13 12:37:17 PDT
Seems reasonable to me (although I'm not a WebKit reviewer). Since this approaches fixes the underlying problem, please also delete the "if (!frame()->view()) return;" statement in FrameView::visibleContentsResized() which was a workaround for the same issue.
Simon Fraser (smfr)
Comment 17 2013-03-13 12:50:49 PDT
Comment on attachment 192962 [details] Alternative patch View in context: https://bugs.webkit.org/attachment.cgi?id=192962&action=review > Source/WebCore/ChangeLog:11 > + Update RenderView so it retrieves the FrameView from the Document instead > + of storing it as a member upon construction. This makes sure that the > + FrameView returned by the RenderView always matches the one of the > + Document. But this implies that the RenderView can retrieve a different FrameView at different times, which is totally unexpected. I think this change is just papering over the cracks. We need to understand why the wrong FrameView is retrieved when the assertion happens.
Mikhail Pozdnyakov
Comment 18 2013-03-22 07:31:58 PDT
*** Bug 112921 has been marked as a duplicate of this bug. ***
Mikhail Pozdnyakov
Comment 19 2013-03-22 07:49:04 PDT
(In reply to comment #17) > (From update of attachment 192962 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=192962&action=review > > > Source/WebCore/ChangeLog:11 > > + Update RenderView so it retrieves the FrameView from the Document instead > > + of storing it as a member upon construction. This makes sure that the > > + FrameView returned by the RenderView always matches the one of the > > + Document. > > But this implies that the RenderView can retrieve a different FrameView at different times, which is totally unexpected. I think this change is just papering over the cracks. We need to understand why the wrong FrameView is retrieved when the assertion happens. The wrong frame view is retrieved because FrameView is created several times for the same frame. The frame however always has the same document instance which has the same renderer (RenderView) and RenderView has the same pointer to FrameView (which is out-dated). There are several ways to fix it, and I am not sure which is the best now. Do we really need different FrameView instances for the same frame? Cannot we re-use the existing one instead of re-creating it? And if we do need to re-create FrameView, we probably need to re-create some other objects (document renderer at least because it contains invalid data otherwise). (I was uploading the exactly same patch to bug#112921, but noticed that the current bug is already addressing the issue :) ).
Mikhail Pozdnyakov
Comment 20 2013-04-04 07:27:58 PDT
Created attachment 196476 [details] another alternative
Simon Fraser (smfr)
Comment 21 2013-04-04 08:36:35 PDT
Comment on attachment 196476 [details] another alternative This is wrong too; you're throwing away a layout that should happen at some point. I think the real issue is the call to setUseFixedLayout() on the page that's going into the page cache. Why does that happen?
Simon Fraser (smfr)
Comment 22 2013-04-04 15:17:18 PDT
So http://trac.webkit.org/changeset/141450 caused setUseFixedLayout() to trigger layout, which seems to be the cause of this bug.
Alexandre Elias
Comment 23 2013-04-04 15:28:27 PDT
(In reply to comment #22) > So http://trac.webkit.org/changeset/141450 caused setUseFixedLayout() to trigger layout, which seems to be the cause of this bug. Yes, in #3 I suggested deleting the call in setUseFixedLayout(). This seems reasonable assuming setUseFixedLayout isn't used in a dynamic manner (which no one does to my knowledge).
Mikhail Pozdnyakov
Comment 24 2013-04-05 06:55:53 PDT
(In reply to comment #23) > (In reply to comment #22) > > So http://trac.webkit.org/changeset/141450 caused setUseFixedLayout() to trigger layout, which seems to be the cause of this bug. > > Yes, in #3 I suggested deleting the call in setUseFixedLayout(). This seems reasonable assuming setUseFixedLayout isn't used in a dynamic manner (which no one does to my knowledge). Unfortunately setUseFixedLayout is used in dynamic manner in WK2 (pls. see void WebPage::setUseFixedLayout(bool fixed) from ./Source/WebKit2/WebProcess/WebPage/WebPage.cpp )
Mikhail Pozdnyakov
Comment 25 2013-04-05 07:07:20 PDT
(In reply to comment #23) > (In reply to comment #22) > > So http://trac.webkit.org/changeset/141450 caused setUseFixedLayout() to trigger layout, which seems to be the cause of this bug. > > Yes, in #3 I suggested deleting the call in setUseFixedLayout(). This seems reasonable assuming setUseFixedLayout isn't used in a dynamic manner (which no one does to my knowledge). The real problem is that frame's document is not updated by the time re-layout is triggered. Checking document for being in cache before re-layout seems to be an appropriate workaround (for me at least :) ). The ideal solution would be changing frame loader logic so that the view is re-created after the appropriate document had been set, but this looks like a quite significant change of the commonly used (and very complex!) code with a huge risk of various regressions.
Note You need to log in before you can comment on or make changes to this bug.