Title: [88147] trunk/Source/WebKit2
Revision
88147
Author
carlo...@webkit.org
Date
2011-06-06 01:35:50 -0700 (Mon, 06 Jun 2011)

Log Message

2011-06-06  Carlos Garcia Campos  <cgar...@igalia.com>

        Reviewed by Anders Carlsson.

        [UNIX] SOCK_DGRAM sockets are not notified when the other end closes the connection
        https://bugs.webkit.org/show_bug.cgi?id=61538

        Use SOCK_STREAM instead of SOCK_DGRAM sockets. Rework the message
        receiver code to support stream sockets, since it requires to
        handle message boundaries. The same code works for DGRAM sockets,
        so this change shouldn't break other ports using DGRAM.

        * Platform/CoreIPC/Connection.h:
        * Platform/CoreIPC/unix/ConnectionUnix.cpp:
        (CoreIPC::Connection::platformInitialize):
        (CoreIPC::Connection::processMessage): Process messages from data
        already received.
        (CoreIPC::readBytesFromSocket): Read from socket using recvmsg().
        (CoreIPC::Connection::readyReadHandler):
        * UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp:
        (WebKit::ProcessLauncher::launchProcess): Use SOCK_DGRAM in
        socketpair().

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (88146 => 88147)


--- trunk/Source/WebKit2/ChangeLog	2011-06-06 08:09:17 UTC (rev 88146)
+++ trunk/Source/WebKit2/ChangeLog	2011-06-06 08:35:50 UTC (rev 88147)
@@ -1 +1,24 @@
+2011-06-06  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        Reviewed by Anders Carlsson.
+
+        [UNIX] SOCK_DGRAM sockets are not notified when the other end closes the connection
+        https://bugs.webkit.org/show_bug.cgi?id=61538
+
+        Use SOCK_STREAM instead of SOCK_DGRAM sockets. Rework the message
+        receiver code to support stream sockets, since it requires to
+        handle message boundaries. The same code works for DGRAM sockets,
+        so this change shouldn't break other ports using DGRAM.
+
+        * Platform/CoreIPC/Connection.h:
+        * Platform/CoreIPC/unix/ConnectionUnix.cpp:
+        (CoreIPC::Connection::platformInitialize):
+        (CoreIPC::Connection::processMessage): Process messages from data
+        already received.
+        (CoreIPC::readBytesFromSocket): Read from socket using recvmsg().
+        (CoreIPC::Connection::readyReadHandler):
+        * UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp:
+        (WebKit::ProcessLauncher::launchProcess): Use SOCK_DGRAM in
+        socketpair().
+
 == Rolled over to ChangeLog-2011-06-04 ==

Modified: trunk/Source/WebKit2/Platform/CoreIPC/Connection.h (88146 => 88147)


--- trunk/Source/WebKit2/Platform/CoreIPC/Connection.h	2011-06-06 08:09:17 UTC (rev 88146)
+++ trunk/Source/WebKit2/Platform/CoreIPC/Connection.h	2011-06-06 08:35:50 UTC (rev 88147)
@@ -337,9 +337,12 @@
 #elif USE(UNIX_DOMAIN_SOCKETS) || OS(SYMBIAN)
     // Called on the connection queue.
     void readyReadHandler();
+    bool processMessage();
 
     Vector<uint8_t> m_readBuffer;
-    size_t m_currentMessageSize;
+    size_t m_readBufferSize;
+    Vector<int> m_fileDescriptors;
+    size_t m_fileDescriptorsSize;
     int m_socketDescriptor;
 
 #if PLATFORM(QT)

Modified: trunk/Source/WebKit2/Platform/CoreIPC/unix/ConnectionUnix.cpp (88146 => 88147)


--- trunk/Source/WebKit2/Platform/CoreIPC/unix/ConnectionUnix.cpp	2011-06-06 08:09:17 UTC (rev 88146)
+++ trunk/Source/WebKit2/Platform/CoreIPC/unix/ConnectionUnix.cpp	2011-06-06 08:35:50 UTC (rev 88147)
@@ -93,7 +93,9 @@
 {
     m_socketDescriptor = identifier;
     m_readBuffer.resize(messageMaxSize);
-    m_currentMessageSize = 0;
+    m_readBufferSize = 0;
+    m_fileDescriptors.resize(attachmentMaxAmount);
+    m_fileDescriptorsSize = 0;
 
 #if PLATFORM(QT)
     m_socketNotifier = 0;
@@ -157,116 +159,181 @@
     T& m_attachments;
 };
 
-void Connection::readyReadHandler()
+bool Connection::processMessage()
 {
+    if (m_readBufferSize < sizeof(MessageInfo))
+        return false;
+
+    uint8_t* messageData = m_readBuffer.data();
+    MessageInfo messageInfo;
+    memcpy(&messageInfo, messageData, sizeof(messageInfo));
+    messageData += sizeof(messageInfo);
+
+    size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(size_t) + (messageInfo.isMessageBodyOOL() ? 0 : messageInfo.bodySize());
+    if (m_readBufferSize < messageLength)
+        return false;
+
     Deque<Attachment> attachments;
-#if PLATFORM(QT)
-    SocketNotifierResourceGuard socketNotifierEnabler(m_socketNotifier);
-#endif
     AttachmentResourceGuard<Deque<Attachment>, Deque<Attachment>::iterator> attachementDisposer(attachments);
+    RefPtr<WebKit::SharedMemory> oolMessageBody;
 
-    OwnArrayPtr<char> attachmentDescriptorBuffer = adoptArrayPtr(new char[CMSG_SPACE(sizeof(int) * (attachmentMaxAmount))]);
-    struct msghdr message;
-    memset(&message, 0, sizeof(message));
+    int attachmentCount = messageInfo.attachmentCount();
+    if (attachmentCount) {
+        OwnArrayPtr<size_t> attachmentSizes = adoptArrayPtr(new size_t[attachmentCount]);
+        memcpy(attachmentSizes.get(), messageData, sizeof(size_t) * attachmentCount);
+        messageData += sizeof(size_t) * attachmentCount;
 
-    struct iovec iov[1];
-    memset(&iov, 0, sizeof(iov));
+        if (messageInfo.isMessageBodyOOL())
+            attachmentCount--;
 
-    message.msg_control = attachmentDescriptorBuffer.get();
-    message.msg_controllen = CMSG_SPACE(sizeof(int) * (attachmentMaxAmount));
+        for (int i = 0; i < attachmentCount; ++i)
+            attachments.append(Attachment(m_fileDescriptors[i], attachmentSizes[i]));
 
-    iov[0].iov_base = m_readBuffer.data();
-    iov[0].iov_len = m_readBuffer.size();
+        if (messageInfo.isMessageBodyOOL()) {
+            ASSERT(messageInfo.bodySize());
 
-    message.msg_iov = iov;
-    message.msg_iovlen = 1;
+            WebKit::SharedMemory::Handle handle;
+            handle.adoptFromAttachment(m_fileDescriptors[attachmentCount], attachmentSizes[attachmentCount]);
+            if (handle.isNull()) {
+                ASSERT_NOT_REACHED();
+                return false;
+            }
 
-
-    int messageLength = 0;
-    while ((messageLength = recvmsg(m_socketDescriptor, &message, 0)) == -1) {
-        if (errno != EINTR)
-            return;
+            oolMessageBody = WebKit::SharedMemory::create(handle, WebKit::SharedMemory::ReadOnly);
+            if (!oolMessageBody) {
+                ASSERT_NOT_REACHED();
+                return false;
+            }
+        }
     }
 
-    struct cmsghdr* controlMessage = CMSG_FIRSTHDR(&message);
+    ASSERT(attachments.size() == messageInfo.isMessageBodyOOL() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount());
 
-    MessageInfo messageInfo;
-    unsigned char* messageData = m_readBuffer.data();
+    uint8_t* messageBody = messageData;
+    if (messageInfo.isMessageBodyOOL())
+        messageBody = reinterpret_cast<uint8_t*>(oolMessageBody->data());
 
-    memcpy(&messageInfo, messageData, sizeof(messageInfo));
-    ASSERT(messageLength == sizeof(messageInfo) + messageInfo.attachmentCount() * sizeof(size_t) + (messageInfo.isMessageBodyOOL() ? 0 : messageInfo.bodySize()));
+    ArgumentDecoder* argumentDecoder;
+    if (attachments.isEmpty())
+        argumentDecoder = new ArgumentDecoder(messageBody, messageInfo.bodySize());
+    else
+        argumentDecoder = new ArgumentDecoder(messageBody, messageInfo.bodySize(), attachments);
 
-    messageData += sizeof(messageInfo);
+    processIncomingMessage(messageInfo.messageID(), adoptPtr(argumentDecoder));
 
-    RefPtr<WebKit::SharedMemory> oolMessageBody;
+    if (m_readBufferSize > messageLength) {
+        memmove(m_readBuffer.data(), m_readBuffer.data() + messageLength, m_readBufferSize - messageLength);
+        m_readBufferSize -= messageLength;
+    } else
+        m_readBufferSize = 0;
 
     if (messageInfo.attachmentCount()) {
-        if (controlMessage && controlMessage->cmsg_level == SOL_SOCKET && controlMessage->cmsg_type == SCM_RIGHTS) {
-            OwnArrayPtr<size_t> attachmentSizes = adoptArrayPtr(new size_t[messageInfo.attachmentCount()]);
-            memcpy(attachmentSizes.get(), messageData, sizeof(size_t) * messageInfo.attachmentCount());
+        if (m_fileDescriptorsSize > messageInfo.attachmentCount()) {
+            size_t fileDescriptorsLength = messageInfo.attachmentCount() * sizeof(int);
+            memmove(m_fileDescriptors.data(), m_fileDescriptors.data() + fileDescriptorsLength, m_fileDescriptorsSize - fileDescriptorsLength);
+            m_fileDescriptorsSize -= fileDescriptorsLength;
+        } else
+            m_fileDescriptorsSize = 0;
+    }
 
-            messageData += sizeof(attachmentSizes);
 
-            OwnArrayPtr<int> fileDescriptors = adoptArrayPtr(new int[messageInfo.attachmentCount()]);
-            memcpy(fileDescriptors.get(), CMSG_DATA(controlMessage), sizeof(int) * messageInfo.attachmentCount());
+    return true;
+}
 
-            int attachmentCount = messageInfo.attachmentCount();
+static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int count, int* fileDescriptors, size_t* fileDescriptorsCount)
+{
+    struct msghdr message;
+    memset(&message, 0, sizeof(message));
 
-            if (messageInfo.isMessageBodyOOL())
-                attachmentCount--;
+    struct iovec iov[1];
+    memset(&iov, 0, sizeof(iov));
 
-            for (int i = 0; i < attachmentCount; ++i) {
-                while (fcntl(fileDescriptors[i], F_SETFL, FD_CLOEXEC) == -1) {
-                    if (errno != EINTR) {
-                        ASSERT_NOT_REACHED();
-                        return;
-                    }
-                }
-            }
+    message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentMaxAmount);
+    OwnArrayPtr<char> attachmentDescriptorBuffer = adoptArrayPtr(new char[message.msg_controllen]);
+    memset(attachmentDescriptorBuffer.get(), 0, message.msg_controllen);
+    message.msg_control = attachmentDescriptorBuffer.get();
 
-            for (int i = 0; i < attachmentCount; ++i)
-                attachments.append(Attachment(fileDescriptors[i], attachmentSizes[i]));
+    iov[0].iov_base = buffer;
+    iov[0].iov_len = count;
 
-            if (messageInfo.isMessageBodyOOL()) {
-                ASSERT(messageInfo.bodySize());
+    message.msg_iov = iov;
+    message.msg_iovlen = 1;
 
-                WebKit::SharedMemory::Handle handle;
-                handle.adoptFromAttachment(fileDescriptors[attachmentCount], attachmentSizes[attachmentCount]);
-                if (handle.isNull()) {
-                    ASSERT_NOT_REACHED();
-                    return;
+    while (true) {
+        ssize_t bytesRead = recvmsg(socketDescriptor, &message, 0);
+
+        if (bytesRead < 0) {
+            if (errno == EINTR)
+                continue;
+
+            return -1;
+        }
+
+        bool found = false;
+        struct cmsghdr* controlMessage;
+        for (controlMessage = CMSG_FIRSTHDR(&message); controlMessage; controlMessage = CMSG_NXTHDR(&message, controlMessage)) {
+            if (controlMessage->cmsg_level == SOL_SOCKET && controlMessage->cmsg_type == SCM_RIGHTS) {
+                *fileDescriptorsCount = (controlMessage->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+                memcpy(fileDescriptors, CMSG_DATA(controlMessage), sizeof(int) * *fileDescriptorsCount);
+
+                for (size_t i = 0; i < *fileDescriptorsCount; ++i) {
+                    while (fcntl(fileDescriptors[i], F_SETFL, FD_CLOEXEC) == -1) {
+                        if (errno != EINTR) {
+                            ASSERT_NOT_REACHED();
+                            break;
+                        }
+                    }
                 }
 
-                oolMessageBody = WebKit::SharedMemory::create(handle, WebKit::SharedMemory::ReadOnly);
-                if (!oolMessageBody) {
-                    ASSERT_NOT_REACHED();
-                    return;
-                }
+                found = true;
+                break;
             }
+        }
 
-            controlMessage = CMSG_NXTHDR(&message, controlMessage);
-        } else {
-            ASSERT_NOT_REACHED();
-            return;
-        }
+        if (!found)
+            *fileDescriptorsCount = 0;
+
+        return bytesRead;
     }
 
-    ASSERT(attachments.size() == messageInfo.isMessageBodyOOL() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount());
+    return -1;
+}
 
-    unsigned char* messageBody = messageData;
+void Connection::readyReadHandler()
+{
+#if PLATFORM(QT)
+    SocketNotifierResourceGuard socketNotifierEnabler(m_socketNotifier);
+#endif
 
-    if (messageInfo.isMessageBodyOOL())
-        messageBody = reinterpret_cast<unsigned char*>(oolMessageBody->data());
+    while (true) {
+        size_t fileDescriptorsCount = 0;
+        size_t bytesToRead = m_readBuffer.size() - m_readBufferSize;
+        ssize_t bytesRead = readBytesFromSocket(m_socketDescriptor, m_readBuffer.data() + m_readBufferSize, bytesToRead,
+                                                m_fileDescriptors.data() + m_fileDescriptorsSize, &fileDescriptorsCount);
 
-    ArgumentDecoder* argumentDecoder;
-    if (attachments.isEmpty())
-        argumentDecoder = new ArgumentDecoder(messageBody, messageInfo.bodySize());
-    else
-        argumentDecoder = new ArgumentDecoder(messageBody, messageInfo.bodySize(), attachments);
+        if (bytesRead < 0) {
+            // EINTR was already handled by readBytesFromSocket.
+            if (errno == EAGAIN || errno == EWOULDBLOCK)
+                return;
 
-    processIncomingMessage(messageInfo.messageID(), adoptPtr(argumentDecoder));
+            // FIXME: Handle other errors here?
+            return;
+        }
 
-    ASSERT(!controlMessage);
+        m_readBufferSize += bytesRead;
+        m_fileDescriptorsSize += fileDescriptorsCount;
+
+        if (!bytesRead) {
+            connectionDidClose();
+            return;
+        }
+
+        // Process messages from data received.
+        while (true) {
+            if (!processMessage())
+                break;
+        }
+    }
 }
 
 bool Connection::open()

Modified: trunk/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp (88146 => 88147)


--- trunk/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp	2011-06-06 08:09:17 UTC (rev 88146)
+++ trunk/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp	2011-06-06 08:35:50 UTC (rev 88147)
@@ -61,7 +61,7 @@
     GPid pid = 0;
 
     int sockets[2];
-    if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) < 0) {
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
         g_printerr("Creation of socket failed: %s.\n", g_strerror(errno));
         ASSERT_NOT_REACHED();
         return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to