<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201595] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201595">201595</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2016-06-02 00:36:21 -0700 (Thu, 02 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Wayland] PlatformDisplayWayland destructor is super crashy
https://bugs.webkit.org/show_bug.cgi?id=157973

Reviewed by Michael Catanzaro.

EGL registers two at exist callbacks one to finish the display and another one to unload drivers, the one to
finish the display happens first. When our destructor is called the _eglFiniDisplay callback has already been
called, so we have a valid pointer for an already finished display. Then eglTerminate tries to find the display
in the global display list, but fails and for some reason it crashes when trying to return an error.
If atexit is called after the global PlatformDisplay constructor, the atexit handler is called before the
destructor. The atexit callbacks are called in reverse order, so if we register an atexit handler after the
global instace has been created and after EGL has been initialized, we could terminate the EGL display before
the EGL atexit handlers and the global PlatformDisplay destructor.

* platform/graphics/PlatformDisplay.cpp:
(WebCore::PlatformDisplay::initializeEGLDisplay):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPlatformDisplaycpp">trunk/Source/WebCore/platform/graphics/PlatformDisplay.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (201594 => 201595)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-06-02 05:47:12 UTC (rev 201594)
+++ trunk/Source/WebCore/ChangeLog        2016-06-02 07:36:21 UTC (rev 201595)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2016-06-02  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [Wayland] PlatformDisplayWayland destructor is super crashy
+        https://bugs.webkit.org/show_bug.cgi?id=157973
+
+        Reviewed by Michael Catanzaro.
+
+        EGL registers two at exist callbacks one to finish the display and another one to unload drivers, the one to
+        finish the display happens first. When our destructor is called the _eglFiniDisplay callback has already been
+        called, so we have a valid pointer for an already finished display. Then eglTerminate tries to find the display
+        in the global display list, but fails and for some reason it crashes when trying to return an error.
+        If atexit is called after the global PlatformDisplay constructor, the atexit handler is called before the
+        destructor. The atexit callbacks are called in reverse order, so if we register an atexit handler after the
+        global instace has been created and after EGL has been initialized, we could terminate the EGL display before
+        the EGL atexit handlers and the global PlatformDisplay destructor.
+
+        * platform/graphics/PlatformDisplay.cpp:
+        (WebCore::PlatformDisplay::initializeEGLDisplay):
+
</ins><span class="cx"> 2016-06-01  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Get rid of StringCapture.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPlatformDisplaycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/PlatformDisplay.cpp (201594 => 201595)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PlatformDisplay.cpp        2016-06-02 05:47:12 UTC (rev 201594)
+++ trunk/Source/WebCore/platform/graphics/PlatformDisplay.cpp        2016-06-02 07:36:21 UTC (rev 201595)
</span><span class="lines">@@ -112,10 +112,8 @@
</span><span class="cx"> 
</span><span class="cx"> PlatformDisplay::~PlatformDisplay()
</span><span class="cx"> {
</span><del>-    // WinCairo crashes when terminating EGL on exit.
-    // https://bugs.webkit.org/show_bug.cgi?id=145832
-#if USE(EGL) &amp;&amp; !PLATFORM(WIN)
-    terminateEGLDisplay();
</del><ins>+#if USE(EGL)
+    ASSERT(m_eglDisplay == EGL_NO_DISPLAY);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -159,10 +157,21 @@
</span><span class="cx">         terminateEGLDisplay();
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+
+    // EGL registers atexit handlers to cleanup its global display list.
+    // Since the global PlatformDisplay instance is created before,
+    // when the PlatformDisplay destructor is called, EGL has already removed the
+    // display from the list, causing eglTerminate() to crash. So, here we register
+    // our own atexit handler, after EGL has been initialized and after the global
+    // instance has been created to ensure we call eglTerminate() before the other
+    // EGL atexit handlers and the PlatformDisplay destructor.
+    // See https://bugs.webkit.org/show_bug.cgi?id=157973.
+    std::atexit([] { PlatformDisplay::sharedDisplay().terminateEGLDisplay(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PlatformDisplay::terminateEGLDisplay()
</span><span class="cx"> {
</span><ins>+    ASSERT(m_eglDisplayInitialized);
</ins><span class="cx">     if (m_eglDisplay == EGL_NO_DISPLAY)
</span><span class="cx">         return;
</span><span class="cx">     eglTerminate(m_eglDisplay);
</span></span></pre>
</div>
</div>

</body>
</html>