<!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>[213031] releases/WebKitGTK/webkit-2.16/Source/WebKit2</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/213031">213031</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2017-02-26 23:52:15 -0800 (Sun, 26 Feb 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/213030">r213030</a> - [GTK] Hangs when showing Google search results
https://bugs.webkit.org/show_bug.cgi?id=168699

Reviewed by Žan Doberšek.

Connection::sendOutgoingMessage() can poll forever if sendmsg fails with EAGAIN or EWOULDBLOCK. For example if
socket read buffers are full, poll will be blocked until we read the pending data, but we can't read because
the thread is blocked in the poll. In case of EAGAIN/EWOULDBLOCK we should poll using the run loop, to allow
reads to happen in thread while we wait for the socket to be writable again. In the GTK+ port we use
GSocketMonitor to poll socket file descriptor without blocking, using the run loop. This patch renames the
socket monitor as readSocketMonitor and adds another one for polling output. When sendmsg fails with
EAGAIN/EWOULDBLOCK, the pending message is saved and the write monitor starts polling. Once the socket is
writable again we send the pending message. Helper class MessageInfo and a new one UnixMessage have been moved
to its own header file to be able to use std::unique_ptr member to save the pending message.

* Platform/IPC/Connection.cpp: Include UnixMessage.h as required by std::unique_ptr.
* Platform/IPC/Connection.h: Add write socket monitor and also keep the GSocket as a member to reuse it.
* Platform/IPC/glib/GSocketMonitor.cpp: Use Function instead of std::function.
(IPC::GSocketMonitor::start):
* Platform/IPC/glib/GSocketMonitor.h:
* Platform/IPC/unix/ConnectionUnix.cpp:
(IPC::Connection::platformInitialize): Initialize the GSocket here since we rely on it to take the ownership of
the descriptor. We were leaking it if the connection was invalidated without being opened.
(IPC::Connection::platformInvalidate): Destroy the GSocket even when not connected. Also stop the write monitor.
(IPC::Connection::processMessage):
(IPC::Connection::open):
(IPC::Connection::platformCanSendOutgoingMessages): Return false if we have a pending message to ensure
Connection doesn't try to send more messages until the pending message is dispatched. We don't need to check
m_isConnected because the caller already checks that.
(IPC::Connection::sendOutgoingMessage): Split it in two. This creates and prepares a UnixMessage and then calls
sendOutputMessage() to do the rest.
(IPC::Connection::sendOutputMessage): Send the message, or save it if sendmsg fails with EAGAIN or EWOULDBLOCK
to be sent later when the socket is writable.
* Platform/IPC/unix/UnixMessage.h: Added.
(IPC::MessageInfo::MessageInfo):
(IPC::MessageInfo::setMessageBodyIsOutOfLine):
(IPC::MessageInfo::isMessageBodyIsOutOfLine):
(IPC::MessageInfo::bodySize):
(IPC::MessageInfo::attachmentCount):
(IPC::UnixMessage::UnixMessage):
(IPC::UnixMessage::~UnixMessage):
(IPC::UnixMessage::attachments):
(IPC::UnixMessage::messageInfo):
(IPC::UnixMessage::body):
(IPC::UnixMessage::bodySize):
(IPC::UnixMessage::appendAttachment):
* PlatformGTK.cmake:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2ChangeLog">releases/WebKitGTK/webkit-2.16/Source/WebKit2/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCConnectioncpp">releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCConnectionh">releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCglibGSocketMonitorcpp">releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCglibGSocketMonitorh">releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCunixConnectionUnixcpp">releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformGTKcmake">releases/WebKitGTK/webkit-2.16/Source/WebKit2/PlatformGTK.cmake</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCunixUnixMessageh">releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/UnixMessage.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit216SourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/ChangeLog (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/ChangeLog        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/ChangeLog        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -1,3 +1,53 @@
</span><ins>+2017-02-26  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Hangs when showing Google search results
+        https://bugs.webkit.org/show_bug.cgi?id=168699
+
+        Reviewed by Žan Doberšek.
+
+        Connection::sendOutgoingMessage() can poll forever if sendmsg fails with EAGAIN or EWOULDBLOCK. For example if
+        socket read buffers are full, poll will be blocked until we read the pending data, but we can't read because
+        the thread is blocked in the poll. In case of EAGAIN/EWOULDBLOCK we should poll using the run loop, to allow
+        reads to happen in thread while we wait for the socket to be writable again. In the GTK+ port we use
+        GSocketMonitor to poll socket file descriptor without blocking, using the run loop. This patch renames the
+        socket monitor as readSocketMonitor and adds another one for polling output. When sendmsg fails with
+        EAGAIN/EWOULDBLOCK, the pending message is saved and the write monitor starts polling. Once the socket is
+        writable again we send the pending message. Helper class MessageInfo and a new one UnixMessage have been moved
+        to its own header file to be able to use std::unique_ptr member to save the pending message.
+
+        * Platform/IPC/Connection.cpp: Include UnixMessage.h as required by std::unique_ptr.
+        * Platform/IPC/Connection.h: Add write socket monitor and also keep the GSocket as a member to reuse it.
+        * Platform/IPC/glib/GSocketMonitor.cpp: Use Function instead of std::function.
+        (IPC::GSocketMonitor::start):
+        * Platform/IPC/glib/GSocketMonitor.h:
+        * Platform/IPC/unix/ConnectionUnix.cpp:
+        (IPC::Connection::platformInitialize): Initialize the GSocket here since we rely on it to take the ownership of
+        the descriptor. We were leaking it if the connection was invalidated without being opened.
+        (IPC::Connection::platformInvalidate): Destroy the GSocket even when not connected. Also stop the write monitor.
+        (IPC::Connection::processMessage):
+        (IPC::Connection::open):
+        (IPC::Connection::platformCanSendOutgoingMessages): Return false if we have a pending message to ensure
+        Connection doesn't try to send more messages until the pending message is dispatched. We don't need to check
+        m_isConnected because the caller already checks that.
+        (IPC::Connection::sendOutgoingMessage): Split it in two. This creates and prepares a UnixMessage and then calls
+        sendOutputMessage() to do the rest.
+        (IPC::Connection::sendOutputMessage): Send the message, or save it if sendmsg fails with EAGAIN or EWOULDBLOCK
+        to be sent later when the socket is writable.
+        * Platform/IPC/unix/UnixMessage.h: Added.
+        (IPC::MessageInfo::MessageInfo):
+        (IPC::MessageInfo::setMessageBodyIsOutOfLine):
+        (IPC::MessageInfo::isMessageBodyIsOutOfLine):
+        (IPC::MessageInfo::bodySize):
+        (IPC::MessageInfo::attachmentCount):
+        (IPC::UnixMessage::UnixMessage):
+        (IPC::UnixMessage::~UnixMessage):
+        (IPC::UnixMessage::attachments):
+        (IPC::UnixMessage::messageInfo):
+        (IPC::UnixMessage::body):
+        (IPC::UnixMessage::bodySize):
+        (IPC::UnixMessage::appendAttachment):
+        * PlatformGTK.cmake:
+
</ins><span class="cx"> 2017-02-20  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove code under USE(GRAPHICS_SURFACE)
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCConnectioncpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.cpp (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.cpp        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.cpp        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -39,6 +39,10 @@
</span><span class="cx"> #include &quot;MachMessage.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if USE(UNIX_DOMAIN_SOCKETS)
+#include &quot;UnixMessage.h&quot;
+#endif
+
</ins><span class="cx"> namespace IPC {
</span><span class="cx"> 
</span><span class="cx"> struct Connection::ReplyHandler {
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCConnectionh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.h (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.h        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/Connection.h        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -79,6 +79,7 @@
</span><span class="cx"> while (0)
</span><span class="cx"> 
</span><span class="cx"> class MachMessage;
</span><ins>+class UnixMessage;
</ins><span class="cx"> 
</span><span class="cx"> class Connection : public ThreadSafeRefCounted&lt;Connection&gt; {
</span><span class="cx"> public:
</span><span class="lines">@@ -308,12 +309,16 @@
</span><span class="cx">     // Called on the connection queue.
</span><span class="cx">     void readyReadHandler();
</span><span class="cx">     bool processMessage();
</span><ins>+    bool sendOutputMessage(UnixMessage&amp;);
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;uint8_t&gt; m_readBuffer;
</span><span class="cx">     Vector&lt;int&gt; m_fileDescriptors;
</span><span class="cx">     int m_socketDescriptor;
</span><ins>+    std::unique_ptr&lt;UnixMessage&gt; m_pendingOutputMessage;
</ins><span class="cx"> #if PLATFORM(GTK)
</span><del>-    GSocketMonitor m_socketMonitor;
</del><ins>+    GRefPtr&lt;GSocket&gt; m_socket;
+    GSocketMonitor m_readSocketMonitor;
+    GSocketMonitor m_writeSocketMonitor;
</ins><span class="cx"> #endif
</span><span class="cx"> #elif OS(DARWIN)
</span><span class="cx">     // Called on the connection queue.
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCglibGSocketMonitorcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.cpp        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx">     return monitor-&gt;m_callback(condition);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void GSocketMonitor::start(GSocket* socket, GIOCondition condition, RunLoop&amp; runLoop, std::function&lt;gboolean (GIOCondition)&gt;&amp;&amp; callback)
</del><ins>+void GSocketMonitor::start(GSocket* socket, GIOCondition condition, RunLoop&amp; runLoop, Function&lt;gboolean (GIOCondition)&gt;&amp;&amp; callback)
</ins><span class="cx"> {
</span><span class="cx">     stop();
</span><span class="cx"> 
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCglibGSocketMonitorh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/glib/GSocketMonitor.h        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     GSocketMonitor() = default;
</span><span class="cx">     ~GSocketMonitor();
</span><span class="cx"> 
</span><del>-    void start(GSocket*, GIOCondition, RunLoop&amp;, std::function&lt;gboolean (GIOCondition)&gt;&amp;&amp;);
</del><ins>+    void start(GSocket*, GIOCondition, RunLoop&amp;, Function&lt;gboolean (GIOCondition)&gt;&amp;&amp;);
</ins><span class="cx">     void stop();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx"> 
</span><span class="cx">     GRefPtr&lt;GSource&gt; m_source;
</span><span class="cx">     GRefPtr&lt;GCancellable&gt; m_cancellable;
</span><del>-    std::function&lt;gboolean (GIOCondition)&gt; m_callback;
</del><ins>+    Function&lt;gboolean (GIOCondition)&gt; m_callback;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace IPC
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCunixConnectionUnixcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DataReference.h&quot;
</span><span class="cx"> #include &quot;SharedMemory.h&quot;
</span><ins>+#include &quot;UnixMessage.h&quot;
</ins><span class="cx"> #include &lt;sys/socket.h&gt;
</span><span class="cx"> #include &lt;unistd.h&gt;
</span><span class="cx"> #include &lt;errno.h&gt;
</span><span class="lines">@@ -60,53 +61,13 @@
</span><span class="cx"> static const size_t messageMaxSize = 4096;
</span><span class="cx"> static const size_t attachmentMaxAmount = 255;
</span><span class="cx"> 
</span><del>-enum {
-    MessageBodyIsOutOfLine = 1U &lt;&lt; 31
-};
-
-class MessageInfo {
-public:
-    MessageInfo() { }
-
-    MessageInfo(size_t bodySize, size_t initialAttachmentCount)
-        : m_bodySize(bodySize)
-        , m_attachmentCount(initialAttachmentCount)
-        , m_isMessageBodyOutOfLine(false)
-    {
-    }
-
-    void setMessageBodyIsOutOfLine()
-    {
-        ASSERT(!isMessageBodyIsOutOfLine());
-
-        m_isMessageBodyOutOfLine = true;
-        m_attachmentCount++;
-    }
-
-    bool isMessageBodyIsOutOfLine() const { return m_isMessageBodyOutOfLine; }
-
-    size_t bodySize() const { return m_bodySize; }
-
-    size_t attachmentCount() const { return m_attachmentCount; }
-
-private:
-    size_t m_bodySize;
-    size_t m_attachmentCount;
-    bool m_isMessageBodyOutOfLine;
-};
-
</del><span class="cx"> class AttachmentInfo {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    AttachmentInfo()
-        : m_type(Attachment::Uninitialized)
-        , m_size(0)
-        , m_isNull(false)
-    {
-    }
</del><ins>+    AttachmentInfo() = default;
</ins><span class="cx"> 
</span><span class="cx">     void setType(Attachment::Type type) { m_type = type; }
</span><del>-    Attachment::Type getType() { return m_type; }
</del><ins>+    Attachment::Type type() const { return m_type; }
</ins><span class="cx">     void setSize(size_t size)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_type == Attachment::MappedMemoryType);
</span><span class="lines">@@ -113,7 +74,7 @@
</span><span class="cx">         m_size = size;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    size_t getSize()
</del><ins>+    size_t size() const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(m_type == Attachment::MappedMemoryType);
</span><span class="cx">         return m_size;
</span><span class="lines">@@ -121,17 +82,20 @@
</span><span class="cx"> 
</span><span class="cx">     // The attachment is not null unless explicitly set.
</span><span class="cx">     void setNull() { m_isNull = true; }
</span><del>-    bool isNull() { return m_isNull; }
</del><ins>+    bool isNull() const { return m_isNull; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    Attachment::Type m_type;
-    size_t m_size;
-    bool m_isNull;
</del><ins>+    Attachment::Type m_type { Attachment::Uninitialized };
+    size_t m_size { 0 };
+    bool m_isNull { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void Connection::platformInitialize(Identifier identifier)
</span><span class="cx"> {
</span><span class="cx">     m_socketDescriptor = identifier;
</span><ins>+#if PLATFORM(GTK)
+    m_socket = adoptGRef(g_socket_new_from_fd(m_socketDescriptor, nullptr));
+#endif
</ins><span class="cx">     m_readBuffer.reserveInitialCapacity(messageMaxSize);
</span><span class="cx">     m_fileDescriptors.reserveInitialCapacity(attachmentMaxAmount);
</span><span class="cx"> }
</span><span class="lines">@@ -138,8 +102,10 @@
</span><span class="cx"> 
</span><span class="cx"> void Connection::platformInvalidate()
</span><span class="cx"> {
</span><del>-    // In GTK+ platform the socket is closed by the work queue.
-#if !PLATFORM(GTK)
</del><ins>+#if PLATFORM(GTK)
+    // In GTK+ platform the socket descriptor is owned by GSocket.
+    m_socket = nullptr;
+#else
</ins><span class="cx">     if (m_socketDescriptor != -1)
</span><span class="cx">         closeWithRetry(m_socketDescriptor);
</span><span class="cx"> #endif
</span><span class="lines">@@ -148,7 +114,8 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(GTK)
</span><del>-    m_socketMonitor.stop();
</del><ins>+    m_readSocketMonitor.stop();
+    m_writeSocketMonitor.stop();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     m_socketDescriptor = -1;
</span><span class="lines">@@ -165,7 +132,7 @@
</span><span class="cx">     memcpy(&amp;messageInfo, messageData, sizeof(messageInfo));
</span><span class="cx">     messageData += sizeof(messageInfo);
</span><span class="cx"> 
</span><del>-    size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(AttachmentInfo) + (messageInfo.isMessageBodyIsOutOfLine() ? 0 : messageInfo.bodySize());
</del><ins>+    size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(AttachmentInfo) + (messageInfo.isBodyOutOfLine() ? 0 : messageInfo.bodySize());
</ins><span class="cx">     if (m_readBuffer.size() &lt; messageLength)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="lines">@@ -179,7 +146,7 @@
</span><span class="cx">         messageData += sizeof(AttachmentInfo) * attachmentCount;
</span><span class="cx"> 
</span><span class="cx">         for (size_t i = 0; i &lt; attachmentCount; ++i) {
</span><del>-            switch (attachmentInfo[i].getType()) {
</del><ins>+            switch (attachmentInfo[i].type()) {
</ins><span class="cx">             case Attachment::MappedMemoryType:
</span><span class="cx">             case Attachment::SocketType:
</span><span class="cx">                 if (!attachmentInfo[i].isNull())
</span><span class="lines">@@ -191,7 +158,7 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (messageInfo.isMessageBodyIsOutOfLine())
</del><ins>+        if (messageInfo.isBodyOutOfLine())
</ins><span class="cx">             attachmentCount--;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -201,11 +168,11 @@
</span><span class="cx">     size_t fdIndex = 0;
</span><span class="cx">     for (size_t i = 0; i &lt; attachmentCount; ++i) {
</span><span class="cx">         int fd = -1;
</span><del>-        switch (attachmentInfo[i].getType()) {
</del><ins>+        switch (attachmentInfo[i].type()) {
</ins><span class="cx">         case Attachment::MappedMemoryType:
</span><span class="cx">             if (!attachmentInfo[i].isNull())
</span><span class="cx">                 fd = m_fileDescriptors[fdIndex++];
</span><del>-            attachments[attachmentCount - i - 1] = Attachment(fd, attachmentInfo[i].getSize());
</del><ins>+            attachments[attachmentCount - i - 1] = Attachment(fd, attachmentInfo[i].size());
</ins><span class="cx">             break;
</span><span class="cx">         case Attachment::SocketType:
</span><span class="cx">             if (!attachmentInfo[i].isNull())
</span><span class="lines">@@ -219,7 +186,7 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (messageInfo.isMessageBodyIsOutOfLine()) {
</del><ins>+    if (messageInfo.isBodyOutOfLine()) {
</ins><span class="cx">         ASSERT(messageInfo.bodySize());
</span><span class="cx"> 
</span><span class="cx">         if (attachmentInfo[attachmentCount].isNull()) {
</span><span class="lines">@@ -228,7 +195,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         WebKit::SharedMemory::Handle handle;
</span><del>-        handle.adoptAttachment(IPC::Attachment(m_fileDescriptors[attachmentFileDescriptorCount - 1], attachmentInfo[attachmentCount].getSize()));
</del><ins>+        handle.adoptAttachment(IPC::Attachment(m_fileDescriptors[attachmentFileDescriptorCount - 1], attachmentInfo[attachmentCount].size()));
</ins><span class="cx"> 
</span><span class="cx">         oolMessageBody = WebKit::SharedMemory::map(handle, WebKit::SharedMemory::Protection::ReadOnly);
</span><span class="cx">         if (!oolMessageBody) {
</span><span class="lines">@@ -237,10 +204,10 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ASSERT(attachments.size() == (messageInfo.isMessageBodyIsOutOfLine() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount()));
</del><ins>+    ASSERT(attachments.size() == (messageInfo.isBodyOutOfLine() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount()));
</ins><span class="cx"> 
</span><span class="cx">     uint8_t* messageBody = messageData;
</span><del>-    if (messageInfo.isMessageBodyIsOutOfLine())
</del><ins>+    if (messageInfo.isBodyOutOfLine())
</ins><span class="cx">         messageBody = reinterpret_cast&lt;uint8_t*&gt;(oolMessageBody-&gt;data());
</span><span class="cx"> 
</span><span class="cx">     auto decoder = std::make_unique&lt;Decoder&gt;(messageBody, messageInfo.bodySize(), nullptr, WTFMove(attachments));
</span><span class="lines">@@ -365,8 +332,7 @@
</span><span class="cx">     RefPtr&lt;Connection&gt; protectedThis(this);
</span><span class="cx">     m_isConnected = true;
</span><span class="cx"> #if PLATFORM(GTK)
</span><del>-    GRefPtr&lt;GSocket&gt; socket = adoptGRef(g_socket_new_from_fd(m_socketDescriptor, nullptr));
-    m_socketMonitor.start(socket.get(), G_IO_IN, m_connectionQueue-&gt;runLoop(), [protectedThis] (GIOCondition condition) -&gt; gboolean {
</del><ins>+    m_readSocketMonitor.start(m_socket.get(), G_IO_IN, m_connectionQueue-&gt;runLoop(), [protectedThis] (GIOCondition condition) -&gt; gboolean {
</ins><span class="cx">         if (condition &amp; G_IO_HUP || condition &amp; G_IO_ERR || condition &amp; G_IO_NVAL) {
</span><span class="cx">             protectedThis-&gt;connectionDidClose();
</span><span class="cx">             return G_SOURCE_REMOVE;
</span><span class="lines">@@ -392,7 +358,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool Connection::platformCanSendOutgoingMessages() const
</span><span class="cx"> {
</span><del>-    return m_isConnected;
</del><ins>+    return !m_pendingOutputMessage;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Connection::sendOutgoingMessage(std::unique_ptr&lt;Encoder&gt; encoder)
</span><span class="lines">@@ -399,15 +365,14 @@
</span><span class="cx"> {
</span><span class="cx">     COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) &lt;= messageMaxSize, AttachmentsFitToMessageInline);
</span><span class="cx"> 
</span><del>-    Vector&lt;Attachment&gt; attachments = encoder-&gt;releaseAttachments();
-    if (attachments.size() &gt; (attachmentMaxAmount - 1)) {
</del><ins>+    UnixMessage outputMessage(*encoder);
+    if (outputMessage.attachments().size() &gt; (attachmentMaxAmount - 1)) {
</ins><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MessageInfo messageInfo(encoder-&gt;bufferSize(), attachments.size());
-    size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder-&gt;bufferSize();
-    if (messageSizeWithBodyInline &gt; messageMaxSize &amp;&amp; encoder-&gt;bufferSize()) {
</del><ins>+    size_t messageSizeWithBodyInline = sizeof(MessageInfo) + (outputMessage.attachments().size() * sizeof(AttachmentInfo)) + outputMessage.bodySize();
+    if (messageSizeWithBodyInline &gt; messageMaxSize &amp;&amp; outputMessage.bodySize()) {
</ins><span class="cx">         RefPtr&lt;WebKit::SharedMemory&gt; oolMessageBody = WebKit::SharedMemory::allocate(encoder-&gt;bufferSize());
</span><span class="cx">         if (!oolMessageBody)
</span><span class="cx">             return false;
</span><span class="lines">@@ -416,13 +381,21 @@
</span><span class="cx">         if (!oolMessageBody-&gt;createHandle(handle, WebKit::SharedMemory::Protection::ReadOnly))
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><del>-        messageInfo.setMessageBodyIsOutOfLine();
</del><ins>+        outputMessage.messageInfo().setBodyOutOfLine();
</ins><span class="cx"> 
</span><del>-        memcpy(oolMessageBody-&gt;data(), encoder-&gt;buffer(), encoder-&gt;bufferSize());
</del><ins>+        memcpy(oolMessageBody-&gt;data(), outputMessage.body(), outputMessage.bodySize());
</ins><span class="cx"> 
</span><del>-        attachments.append(handle.releaseAttachment());
</del><ins>+        outputMessage.appendAttachment(handle.releaseAttachment());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    return sendOutputMessage(outputMessage);
+}
+
+bool Connection::sendOutputMessage(UnixMessage&amp; outputMessage)
+{
+    ASSERT(!m_pendingOutputMessage);
+
+    auto&amp; messageInfo = outputMessage.messageInfo();
</ins><span class="cx">     struct msghdr message;
</span><span class="cx">     memset(&amp;message, 0, sizeof(message));
</span><span class="cx"> 
</span><span class="lines">@@ -438,6 +411,7 @@
</span><span class="cx">     std::unique_ptr&lt;AttachmentInfo[]&gt; attachmentInfo;
</span><span class="cx">     MallocPtr&lt;char&gt; attachmentFDBuffer;
</span><span class="cx"> 
</span><ins>+    auto&amp; attachments = outputMessage.attachments();
</ins><span class="cx">     if (!attachments.isEmpty()) {
</span><span class="cx">         int* fdPtr = 0;
</span><span class="cx"> 
</span><span class="lines">@@ -488,9 +462,9 @@
</span><span class="cx">         ++iovLength;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!messageInfo.isMessageBodyIsOutOfLine() &amp;&amp; encoder-&gt;bufferSize()) {
-        iov[iovLength].iov_base = reinterpret_cast&lt;void*&gt;(encoder-&gt;buffer());
-        iov[iovLength].iov_len = encoder-&gt;bufferSize();
</del><ins>+    if (!messageInfo.isBodyOutOfLine() &amp;&amp; outputMessage.bodySize()) {
+        iov[iovLength].iov_base = reinterpret_cast&lt;void*&gt;(outputMessage.body());
+        iov[iovLength].iov_len = outputMessage.bodySize();
</ins><span class="cx">         ++iovLength;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -500,6 +474,25 @@
</span><span class="cx">         if (errno == EINTR)
</span><span class="cx">             continue;
</span><span class="cx">         if (errno == EAGAIN || errno == EWOULDBLOCK) {
</span><ins>+#if PLATFORM(GTK)
+            m_pendingOutputMessage = std::make_unique&lt;UnixMessage&gt;(WTFMove(outputMessage));
+            m_writeSocketMonitor.start(m_socket.get(), G_IO_OUT, m_connectionQueue-&gt;runLoop(), [this, protectedThis = makeRef(*this)] (GIOCondition condition) -&gt; gboolean {
+                if (condition &amp; G_IO_OUT) {
+                    ASSERT(m_pendingOutputMessage);
+                    // We can't stop the monitor from this lambda, because stop destroys the lambda.
+                    m_connectionQueue-&gt;dispatch([this, protectedThis = makeRef(*this)] {
+                        m_writeSocketMonitor.stop();
+                        auto message = WTFMove(m_pendingOutputMessage);
+                        if (m_isConnected) {
+                            sendOutputMessage(*message);
+                            sendOutgoingMessages();
+                        }
+                    });
+                }
+                return G_SOURCE_REMOVE;
+            });
+            return false;
+#else
</ins><span class="cx">             struct pollfd pollfd;
</span><span class="cx"> 
</span><span class="cx">             pollfd.fd = m_socketDescriptor;
</span><span class="lines">@@ -507,6 +500,7 @@
</span><span class="cx">             pollfd.revents = 0;
</span><span class="cx">             poll(&amp;pollfd, 1, -1);
</span><span class="cx">             continue;
</span><ins>+#endif
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_isConnected)
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformIPCunixUnixMessageh"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/UnixMessage.h (0 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/UnixMessage.h                                (rev 0)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/Platform/IPC/unix/UnixMessage.h        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011,2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;Attachment.h&quot;
+#include &lt;wtf/Vector.h&gt;
+
+namespace IPC {
+
+class MessageInfo {
+public:
+    MessageInfo() = default;
+
+    MessageInfo(size_t bodySize, size_t initialAttachmentCount)
+        : m_bodySize(bodySize)
+        , m_attachmentCount(initialAttachmentCount)
+    {
+    }
+
+    void setBodyOutOfLine()
+    {
+        ASSERT(!isBodyOutOfLine());
+
+        m_isBodyOutOfLine = true;
+        m_attachmentCount++;
+    }
+
+    bool isBodyOutOfLine() const { return m_isBodyOutOfLine; }
+    size_t bodySize() const { return m_bodySize; }
+    size_t attachmentCount() const { return m_attachmentCount; }
+
+private:
+    size_t m_bodySize { 0 };
+    size_t m_attachmentCount { 0 };
+    bool m_isBodyOutOfLine { false };
+};
+
+class UnixMessage {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    UnixMessage(Encoder&amp; encoder)
+        : m_attachments(encoder.releaseAttachments())
+        , m_messageInfo(encoder.bufferSize(), m_attachments.size())
+        , m_body(encoder.buffer())
+    {
+    }
+
+    UnixMessage(UnixMessage&amp;&amp; other)
+    {
+        m_attachments = WTFMove(other.m_attachments);
+        m_messageInfo = WTFMove(other.m_messageInfo);
+        if (other.m_bodyOwned) {
+            std::swap(m_body, other.m_body);
+            std::swap(m_bodyOwned, other.m_bodyOwned);
+        } else if (!m_messageInfo.isBodyOutOfLine()) {
+            m_body = static_cast&lt;uint8_t*&gt;(fastMalloc(m_messageInfo.bodySize()));
+            memcpy(m_body, other.m_body, m_messageInfo.bodySize());
+            m_bodyOwned = true;
+            other.m_body = nullptr;
+            other.m_bodyOwned = false;
+        }
+    }
+
+    ~UnixMessage()
+    {
+        if (m_bodyOwned)
+            fastFree(m_body);
+    }
+
+    const Vector&lt;Attachment&gt;&amp; attachments() const { return m_attachments; }
+    MessageInfo&amp; messageInfo() { return m_messageInfo; }
+
+    uint8_t* body() const { return m_body; }
+    size_t bodySize() const  { return m_messageInfo.bodySize(); }
+
+    void appendAttachment(Attachment&amp;&amp; attachment)
+    {
+        m_attachments.append(WTFMove(attachment));
+    }
+
+private:
+    Vector&lt;Attachment&gt; m_attachments;
+    MessageInfo m_messageInfo;
+    uint8_t* m_body { nullptr };
+    bool m_bodyOwned { false };
+};
+
+} // namespace IPC
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebKit2PlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebKit2/PlatformGTK.cmake (213030 => 213031)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebKit2/PlatformGTK.cmake        2017-02-27 07:50:31 UTC (rev 213030)
+++ releases/WebKitGTK/webkit-2.16/Source/WebKit2/PlatformGTK.cmake        2017-02-27 07:52:15 UTC (rev 213031)
</span><span class="lines">@@ -850,6 +850,7 @@
</span><span class="cx">     &quot;${WEBKIT2_DIR}/NetworkProcess/soup&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/NetworkProcess/unix&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/Platform/IPC/glib&quot;
</span><ins>+    &quot;${WEBKIT2_DIR}/Platform/IPC/unix&quot;
</ins><span class="cx">     &quot;${WEBKIT2_DIR}/Shared/API/c/gtk&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/Shared/Plugins/unix&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/Shared/glib&quot;
</span></span></pre>
</div>
</div>

</body>
</html>