<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:0in;
        margin-left:.5in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
span.EmailStyle18
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
span.EmailStyle19
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.EmailStyle20
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:563685761;
        mso-list-type:hybrid;
        mso-list-template-ids:2091671508 1729264860 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:-;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Calibri","sans-serif";
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l0:level2
        {mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level3
        {mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level4
        {mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level5
        {mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level6
        {mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level7
        {mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level8
        {mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level9
        {mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l1
        {mso-list-id:1768037810;
        mso-list-type:hybrid;
        mso-list-template-ids:-595064844 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l1:level1
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l1:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l1:level3
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l1:level4
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l1:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l1:level6
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l1:level7
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l1:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l1:level9
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="color:#1F497D">Vincent,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">I’ve also embedded WebKit in a .NET application, and I’ve seen similar issues – not exactly what you’re seeing though.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">Maybe some tips I’ve learned could be of help to you or others:<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-.25in;mso-list:l1 level1 lfo3"><![if !supportLists]><span style="font-family:Symbol;color:#1F497D"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span style="color:#1F497D">Calling DestroyWindow will cause WebView::close() to be called (when WM_DESTROY is received), but it does not cause WebView’s destructor to be called, that doesn’t happen until the RCW holding the last
COM reference is destroyed and the COM ref count goes to 0. This happens on the GC thread (.NET internals), and deleting core webkit objects from a thread besides the main thread can lead to undefined behavior. I’d see crashes from concurrent javascript
GCs. I fixed this by marshaling the delete call back to the main thread (in every single COM exposed class).<o:p></o:p></span></p>
<p class="MsoListParagraph" style="text-indent:-.25in;mso-list:l1 level1 lfo3"><![if !supportLists]><span style="font-family:Symbol;color:#1F497D"><span style="mso-list:Ignore">·<span style="font:7.0pt "Times New Roman"">
</span></span></span><![endif]><span style="color:#1F497D">WebView’s destructor calls DestroyWindow() on a tool tip window which may or may not have been destroyed (at least on WinCE). When embedding in a .NET application, there can be a decent gap between
the time the WebView’s window is destroyed and the destructor is called. It’s possible that in the instances when Windows destroyed the tool tip window (because it is a child of the webview window) that the tool tip handle is assigned to another window by
the time WebView’s destructor is called. You can guess what happens then when WebView’s destructor deletes the tool tip window. Windows in the system disappear – sometimes causing a crash. The only fix I could figure out what to check to see if the window
is still a tool tip window before deleting it.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">I don’t know if anyone wants to see a patch land for either of these problems, they’re confined to embedded WebKit on Windows under .NET…<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">Mark<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> webkit-dev-bounces@lists.webkit.org [mailto:webkit-dev-bounces@lists.webkit.org]
<b>On Behalf Of </b>Van Den Berghe, Vincent<br>
<b>Sent:</b> Friday, September 13, 2013 1:43 AM<br>
<b>To:</b> webkit-dev@lists.webkit.org<br>
<b>Subject:</b> [webkit-dev] TimerWindowWndProc and dangling page instances<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Hello,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Background<o:p></o:p></p>
<p class="MsoNormal">---------------<o:p></o:p></p>
<p class="MsoNormal">I’m currently embedding WebKit in a .NET application, which required me to solve a whole set of issues that are not relevant here. However, I’ve stumbled upon a scenario which I suspect is *<b>really</b>* problematic (but I can be wrong).
Before patching anything, I’d like to submit this to greater minds for validation. The version of WebKit to which this applies is irrelevant: any recent version will do.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Problem<o:p></o:p></p>
<p class="MsoNormal">----------<o:p></o:p></p>
<p class="MsoNormal">When I’m finish with a WebView instance and before I’m releasing the COM object, I close it by doing a
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="text-indent:.5in">DestroyWindow(m_viewWindow) <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">…where m_viewWindow is WebView’s view window. Note that calling WebView::close() would work just as well.<o:p></o:p></p>
<p class="MsoNormal">This triggers a sequence of events that ultimately causes the destructor of the page to be called:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="text-indent:.5in">Page::~Page()<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">This works well, but when stress testing this will crash the WebKit.DLL with the following stack trace:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"> WebKit.dll!WebCore::setImageLoadingSettings(WebCore::Page * page) Line 57 + 0x3 bytes C++<o:p></o:p></p>
<p class="MsoNormal"> WebKit.dll!WebCore::Settings::imageLoadingSettingsTimerFired(WebCore::Timer<WebCore::Settings> * __formal) Line 363 + 0x8 bytes C++<o:p></o:p></p>
<p class="MsoNormal"> WebKit.dll!WebCore::Timer<WebCore::XMLHttpRequestProgressEventThrottle>::fired() Line 114 + 0xb bytes C++<o:p></o:p></p>
<p class="MsoNormal"> WebKit.dll!WebCore::ThreadTimers::sharedTimerFiredInternal() Line 132 C++<o:p></o:p></p>
<p class="MsoNormal"> WebKit.dll!WebCore::TimerWindowWndProc(HWND__ * hWnd, unsigned int message, unsigned int wParam, long lParam) Line 111 C++<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Depending on the managed environment (details are irrelevant for this discussion), the crash happens either immediately or after a while. Because of the way I embed WebKit, this usually happens when the second (or third, forth…) instance
is being created.<o:p></o:p></p>
<p class="MsoNormal">The visible cause of the crash is the call to <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="text-indent:.5in">WebKit.dll!WebCore::setImageLoadingSettings(WebCore::Page * page)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">... with a page instance for which its destructor has already been executed.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Primary Cause<o:p></o:p></p>
<p class="MsoNormal">-----------------<o:p></o:p></p>
<p class="MsoNormal">I suspect the primary cause of a crash is the pending timer whose message is still in the message queue, that is executed just after the destruction of the page, but before any pending timers are killed. This causes a delayed execution
of a function on a dangling page instance.<o:p></o:p></p>
<p class="MsoNormal">The problem doesn’t occur when I don’t call DestroyWindow or WebView::Close(), but this leads to unacceptable memory leaks.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Workaround<o:p></o:p></p>
<p class="MsoNormal">---------------<o:p></o:p></p>
<p class="MsoNormal">The minimal (but far from elegant) workaround is to add a method to WebCore::Settings:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">
<span style="color:blue">void</span> clearPage()<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> m_page = 0;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> }<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">And call this method as the first line of Page’s destructor:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-left:.5in;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">Page::~Page()<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:.5in;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">{<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:.5in;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> m_settings->clearPage();<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:.5in;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> m_mainFrame->setView(0);<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:.5in;text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">…<o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left:.5in"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">…and finally add a <span style="font-size:9.5pt;font-family:Consolas;color:blue">
if</span><span style="font-size:9.5pt;font-family:Consolas">(page)</span> guard in setImageLoadingSettings like so:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas;color:blue">static</span><span style="font-size:9.5pt;font-family:Consolas">
<span style="color:blue">void</span> setImageLoadingSettings(Page* page)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">{<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">
<span style="color:blue">if</span>(page)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">
<span style="color:blue">for</span> (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> frame->document()->cachedResourceLoader()->setImagesEnabled(page->settings().areImagesEnabled());<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> frame->document()->cachedResourceLoader()->setAutoLoadImages(page->settings().loadsImagesAutomatically());<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"> }<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas">}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:9.5pt;font-family:Consolas"><o:p> </o:p></span></p>
<p class="MsoNormal">This doesn’t remedy the delayed execution of the timer, but solves the problem by setting the deleted instance to NULL and making sure it’s not used in the delayed call.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The questions of course are:<o:p></o:p></p>
<p class="MsoListParagraph" style="text-indent:-.25in;mso-list:l0 level1 lfo2"><![if !supportLists]><span style="mso-list:Ignore">-<span style="font:7.0pt "Times New Roman"">
</span></span><![endif]>Is this behavior by design?<o:p></o:p></p>
<p class="MsoListParagraph" style="text-indent:-.25in;mso-list:l0 level1 lfo2"><![if !supportLists]><span style="mso-list:Ignore">-<span style="font:7.0pt "Times New Roman"">
</span></span><![endif]>If it is, is there a way to clean up WebKit instances without causing this crashing behavior, and if so which one?<o:p></o:p></p>
<p class="MsoListParagraph" style="text-indent:-.25in;mso-list:l0 level1 lfo2"><![if !supportLists]><span style="mso-list:Ignore">-<span style="font:7.0pt "Times New Roman"">
</span></span><![endif]>If it isn’t, is there a more elegant workaround than the one outlined here?<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks for any feedback,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Vincent<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>