Bug 85058 - [EFL][DRT] ewk_view_paint_contents may trigger assertion failure
Summary: [EFL][DRT] ewk_view_paint_contents may trigger assertion failure
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit EFL (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Dominik Röttsches (drott)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-04-27 06:10 PDT by Dominik Röttsches (drott)
Modified: 2012-05-10 09:53 PDT (History)
12 users (show)

See Also:


Attachments
Don't go into painting without layout (2.70 KB, patch)
2012-04-27 06:18 PDT, Dominik Röttsches (drott)
no flags Details | Formatted Diff | Diff
Updated, rebased patch. (3.27 KB, patch)
2012-05-10 05:35 PDT, Dominik Röttsches (drott)
no flags Details | Formatted Diff | Diff
Updated, review comment addressed. (3.68 KB, patch)
2012-05-10 07:27 PDT, Dominik Röttsches (drott)
no flags Details | Formatted Diff | Diff
Updated again. (3.59 KB, patch)
2012-05-10 07:49 PDT, Dominik Röttsches (drott)
no flags Details | Formatted Diff | Diff
Updated patch (3.90 KB, patch)
2012-05-10 08:11 PDT, Dominik Röttsches (drott)
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dominik Röttsches (drott) 2012-04-27 06:10:08 PDT
We're running into an assertion failure in
WebCore::FrameView::paintContents
ASSERTION FAILED: !needsLayout()

when running media/media-fragments/ tests.

ewk_view_paint resolves that by calling

    if (view->needsLayout())
        view->forceLayout();

So we should probably do that in ewk_view_paint_contents, too.
Comment 1 Dominik Röttsches (drott) 2012-04-27 06:18:42 PDT
Created attachment 139185 [details]
Don't go into painting without layout
Comment 2 Gyuyoung Kim 2012-05-02 03:51:31 PDT
Comment on attachment 139185 [details]
Don't go into painting without layout

View in context: https://bugs.webkit.org/attachment.cgi?id=139185&action=review

> Source/WebKit/efl/ewk/ewk_view.cpp:2740
> +        view->forceLayout();

I'm wondering whether we should call forceLayout(). As you know, there is view->layout().
Comment 3 Dominik Röttsches (drott) 2012-05-02 04:01:31 PDT
They are identical - forceLayout calls layout internally - and I don't see any deprecation warning in FrameView.h. I am using forceLayout for consistency with ewk_view_paint: forceLayout is used there. So, looks okay to you?
Comment 4 Ryuan Choi 2012-05-02 04:31:29 PDT
(In reply to comment #3)
> They are identical - forceLayout calls layout internally - and I don't see any deprecation warning in FrameView.h. I am using forceLayout for consistency with ewk_view_paint: forceLayout is used there. So, looks okay to you?

I think that we should investigate this more.

If contents is dynamic, each tile may render different layout for ewk_view_pre_render.
ewk_view_pre_render make several tiles render on idle time.

Add jungjik in CCs.
Comment 5 Gyuyoung Kim 2012-05-02 04:49:50 PDT
I think we should avoid unneeded layout operation. Because, layout cost is expensive.
Comment 6 Dominik Röttsches (drott) 2012-05-02 05:13:13 PDT
Sure, but it's not unneeded here - since without a layout we run into the assertion failure, so clearly something is wrong. 
Jungjik, Ryuan - which direction do you think we should look to investigate this, any pointers? Which component should have done the layout before we actually get to ewk_view_paint_contents and run into the assertion failure?
Comment 7 Dominik Röttsches (drott) 2012-05-10 05:11:38 PDT
The media fragment tests are constructed in a way that they quickly iterate through a number of fragment suffixes that they append to the media URL. After each test, they add elements to the DOM to report the result of the test case using .innerHTML which goes through the parser and ends up adding child elements to the DOM.

We hit the assertion failure because of a race condition. Idle-repainting of EFL fights with the scheduleRelayout() timer that is triggered by the addChild insertion.

HTMLConstructionSite::executeTask gets to
 task.parent->parserAddChild(task.child.get());

that triggers as a child note insertion notification in:
ChildNodeInsertionNotifier::notifyInsertedIntoDocument

which in turn triggers a
        view->scheduleRelayout();

in HTMLBodyElement::didNotifyDescendantInseretions.
which has the following interesting fixme:
    // FIXME: This call to scheduleRelayout should not be needed here.
    // But without it we hang during WebKit tests; need to fix that and remove this.

Now, if the EFL idle tiling repainting timer is triggered first, we arrive in ewk_view_paint_contents without having done a relayout. 

So, I would conclude, it's safe to do a layout here if needed to avoid this assertion failure.
  if (view->needsLayout())
      view->forceLayout();

Since a relayout would be done anyway if the scheduleRelayout timer would fire first before we get to idle.
Comment 8 Dominik Röttsches (drott) 2012-05-10 05:35:49 PDT
Created attachment 141154 [details]
Updated, rebased patch.

Updated changelog to include reason for why assertion is hit.
Comment 9 Gustavo Noronha (kov) 2012-05-10 05:52:23 PDT
Comment on attachment 141154 [details]
Updated, rebased patch.

View in context: https://bugs.webkit.org/attachment.cgi?id=141154&action=review

> Source/WebKit/efl/ewk/ewk_view.cpp:2810
> +    if (view->needsLayout())
> +        view->forceLayout();

To me this looks like using too strong a force. Why don't you call view->updateLayoutAndStyleIfNeededRecursive() unconditionally instead?
Comment 10 Dominik Röttsches (drott) 2012-05-10 07:27:49 PDT
Created attachment 141165 [details]
Updated, review comment addressed.

Using less force, Luke. Thanks, kov!
Comment 11 Dominik Röttsches (drott) 2012-05-10 07:28:41 PDT
Comment on attachment 141165 [details]
Updated, review comment addressed.

Clearing flags, forgot something.
Comment 12 Dominik Röttsches (drott) 2012-05-10 07:49:46 PDT
Created attachment 141170 [details]
Updated again.
Comment 13 Dominik Röttsches (drott) 2012-05-10 07:53:32 PDT
Thought about it again - updateLayoutAndStyleIfNeededRecursive() does nothing else than if(needsLayout()) layout() as well. We don't actually need to update style, I believe. We just need to protect against the race condition where the idle timer tries to repaint first before layoutTimerFired is called, so this conditional layout() call should be enough here. To make it sound less forceful, I call the layout() function, which is equivalent.
Comment 14 Dominik Röttsches (drott) 2012-05-10 08:11:51 PDT
Created attachment 141174 [details]
Updated patch

Following reviewer's advice here and finally using updateLayoutAndStyleIfNeededRecursive() - thanks.
Comment 15 WebKit Review Bot 2012-05-10 09:53:18 PDT
Comment on attachment 141174 [details]
Updated patch

Clearing flags on attachment: 141174

Committed r116656: <http://trac.webkit.org/changeset/116656>
Comment 16 WebKit Review Bot 2012-05-10 09:53:25 PDT
All reviewed patches have been landed.  Closing bug.