Bug 147128

Summary: RemoteLayerTreeDisplayRefreshMonitor occasionally outlives its RemoteLayerTreeDrawingArea
Product: WebKit Reporter: Wenson Hsieh <wenson_hsieh>
Component: WebCore Misc.Assignee: Nobody <webkit-unassigned>
Status: RESOLVED INVALID    
Severity: Normal CC: ap, simon.fraser, thorton
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: iPhone / iPad   
OS: Unspecified   

Description Wenson Hsieh 2015-07-20 15:56:14 PDT
A RemoteLayerTreeDisplayRefreshMonitor's RemoteLayerTreeDrawingArea should always outlive it. However, as the crash in https://bugs.webkit.org/show_bug.cgi?id=147124 demonstrated, this is not always the case. Discover why this occurs on pages using requestAnimationFrame, and fix it.
Comment 1 Wenson Hsieh 2015-07-21 09:56:31 PDT
Upon further investigation, it looks like the refresh monitor outliving its drawing area is, in fact, not incorrect behavior. A Document keeps its ScriptedAnimationController alive, and may be kept alive independently of its Page or WebPage (and hence, the WebPage's drawing area). Through the registration/ unregistration process in the DisplayRefreshMonitorManager, the ScriptedAnimationController of a Document that has changed owners may actually keep a RemoteLayerTreeDisplayRefreshMonitor alive. When the drawing area previously associated with this RemoteLayerTreeDisplayRefreshMonitor is deallocated due to the page being destroyed, the RemoteLayerTreeDisplayRefreshMonitor that is being kept alive indirectly through the Document should go down with it.

In summary, the fix to https://bugs.webkit.org/show_bug.cgi?id=147124 should make sense, considering that our original assumptions about the drawing area always outliving all of its monitors was incorrect to begin with.

For future reference, I was able to find a sequence of steps that reliably reproduce this behavior.

1. Add an assertion or debugging statement in ~RemoteLayerTreeDrawingArea that triggers when m_displayRefreshMonitors.size() > 0.
2. Open Safari
3. Navigate to whsieh.github.io/examples/iframes.html
4. Navigate to whsieh.github.io/examples/iframes.html again
5. Quickly navigate back (swipe or use the back button)
6. Quickly navigate forwards (swipe or use the forward button)
7. Repeat steps 4 and 5 one or two more times
8. Close the tab
9. The assertion or debugging statement in (1) should fire. If this is not the case, repeat again (it may take a few attempts).

Using the above steps, I was able to reproduce the bug on an iPhone 6 roughly once every 3 attempts.