diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebKit2/Platform/IPC/unix | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebKit2/Platform/IPC/unix')
-rw-r--r-- | Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp | 24 | ||||
-rw-r--r-- | Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp | 348 | ||||
-rw-r--r-- | Source/WebKit2/Platform/IPC/unix/UnixMessage.h | 113 |
3 files changed, 303 insertions, 182 deletions
diff --git a/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp b/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp index 022c72d41..218711645 100644 --- a/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp +++ b/Source/WebKit2/Platform/IPC/unix/AttachmentUnix.cpp @@ -45,7 +45,29 @@ Attachment::Attachment(int fileDescriptor) { } -void Attachment::dispose() +Attachment::Attachment(Attachment&& attachment) + : m_type(attachment.m_type) + , m_fileDescriptor(attachment.m_fileDescriptor) + , m_size(attachment.m_size) +{ + attachment.m_type = Uninitialized; + attachment.m_fileDescriptor = -1; + attachment.m_size = 0; +} + +Attachment& Attachment::operator=(Attachment&& attachment) +{ + m_type = attachment.m_type; + attachment.m_type = Uninitialized; + m_fileDescriptor = attachment.m_fileDescriptor; + attachment.m_fileDescriptor = -1; + m_size = attachment.m_size; + attachment.m_size = 0; + + return *this; +} + +Attachment::~Attachment() { if (m_fileDescriptor != -1) closeWithRetry(m_fileDescriptor); diff --git a/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp b/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp index dbadd26a3..7d564a449 100644 --- a/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp +++ b/Source/WebKit2/Platform/IPC/unix/ConnectionUnix.cpp @@ -30,21 +30,23 @@ #include "DataReference.h" #include "SharedMemory.h" +#include "UnixMessage.h" #include <sys/socket.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <poll.h> #include <wtf/Assertions.h> -#include <wtf/Functional.h> #include <wtf/StdLibExtras.h> #include <wtf/UniStdExtras.h> #if PLATFORM(GTK) -#include <glib.h> +#include <gio/gio.h> #endif -#ifdef SOCK_SEQPACKET +// Although it's available on Darwin, SOCK_SEQPACKET seems to work differently +// than in traditional Unix so fallback to STREAM on that platform. +#if defined(SOCK_SEQPACKET) && !OS(DARWIN) #define SOCKET_TYPE SOCK_SEQPACKET #else #if PLATFORM(GTK) @@ -59,59 +61,20 @@ namespace IPC { static const size_t messageMaxSize = 4096; static const size_t attachmentMaxAmount = 255; -enum { - MessageBodyIsOutOfLine = 1U << 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; -}; - class AttachmentInfo { + WTF_MAKE_FAST_ALLOCATED; public: - AttachmentInfo() - : m_type(Attachment::Uninitialized) - , m_size(0) - , m_isNull(false) - { - } + AttachmentInfo() = default; void setType(Attachment::Type type) { m_type = type; } - Attachment::Type getType() { return m_type; } + Attachment::Type type() const { return m_type; } void setSize(size_t size) { ASSERT(m_type == Attachment::MappedMemoryType); m_size = size; } - size_t getSize() + size_t size() const { ASSERT(m_type == Attachment::MappedMemoryType); return m_size; @@ -119,27 +82,30 @@ public: // The attachment is not null unless explicitly set. void setNull() { m_isNull = true; } - bool isNull() { return m_isNull; } + bool isNull() const { return m_isNull; } private: - Attachment::Type m_type; - size_t m_size; - bool m_isNull; + Attachment::Type m_type { Attachment::Uninitialized }; + size_t m_size { 0 }; + bool m_isNull { false }; }; void Connection::platformInitialize(Identifier identifier) { m_socketDescriptor = identifier; - m_readBuffer.resize(messageMaxSize); - m_readBufferSize = 0; - m_fileDescriptors.resize(attachmentMaxAmount); - m_fileDescriptorsSize = 0; +#if PLATFORM(GTK) + m_socket = adoptGRef(g_socket_new_from_fd(m_socketDescriptor, nullptr)); +#endif + m_readBuffer.reserveInitialCapacity(messageMaxSize); + m_fileDescriptors.reserveInitialCapacity(attachmentMaxAmount); } void Connection::platformInvalidate() { - // In GTK+ platform the socket is closed by the work queue. -#if !PLATFORM(GTK) +#if PLATFORM(GTK) + // In GTK+ platform the socket descriptor is owned by GSocket. + m_socket = nullptr; +#else if (m_socketDescriptor != -1) closeWithRetry(m_socketDescriptor); #endif @@ -147,34 +113,18 @@ void Connection::platformInvalidate() if (!m_isConnected) return; -#if PLATFORM(GTK) || PLATFORM(EFL) - m_connectionQueue->unregisterSocketEventHandler(m_socketDescriptor); +#if PLATFORM(GTK) + m_readSocketMonitor.stop(); + m_writeSocketMonitor.stop(); #endif m_socketDescriptor = -1; m_isConnected = false; } -template<class T, class iterator> -class AttachmentResourceGuard { -public: - AttachmentResourceGuard(T& attachments) - : m_attachments(attachments) - { - } - ~AttachmentResourceGuard() - { - iterator end = m_attachments.end(); - for (iterator i = m_attachments.begin(); i != end; ++i) - i->dispose(); - } -private: - T& m_attachments; -}; - bool Connection::processMessage() { - if (m_readBufferSize < sizeof(MessageInfo)) + if (m_readBuffer.size() < sizeof(MessageInfo)) return false; uint8_t* messageData = m_readBuffer.data(); @@ -182,8 +132,13 @@ bool Connection::processMessage() memcpy(&messageInfo, messageData, sizeof(messageInfo)); messageData += sizeof(messageInfo); - size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(AttachmentInfo) + (messageInfo.isMessageBodyIsOutOfLine() ? 0 : messageInfo.bodySize()); - if (m_readBufferSize < messageLength) + if (messageInfo.attachmentCount() > attachmentMaxAmount || (!messageInfo.isBodyOutOfLine() && messageInfo.bodySize() > messageMaxSize)) { + ASSERT_NOT_REACHED(); + return false; + } + + size_t messageLength = sizeof(MessageInfo) + messageInfo.attachmentCount() * sizeof(AttachmentInfo) + (messageInfo.isBodyOutOfLine() ? 0 : messageInfo.bodySize()); + if (m_readBuffer.size() < messageLength) return false; size_t attachmentFileDescriptorCount = 0; @@ -196,7 +151,7 @@ bool Connection::processMessage() messageData += sizeof(AttachmentInfo) * attachmentCount; for (size_t i = 0; i < attachmentCount; ++i) { - switch (attachmentInfo[i].getType()) { + switch (attachmentInfo[i].type()) { case Attachment::MappedMemoryType: case Attachment::SocketType: if (!attachmentInfo[i].isNull()) @@ -204,27 +159,25 @@ bool Connection::processMessage() break; case Attachment::Uninitialized: default: - ASSERT_NOT_REACHED(); break; } } - if (messageInfo.isMessageBodyIsOutOfLine()) + if (messageInfo.isBodyOutOfLine()) attachmentCount--; } Vector<Attachment> attachments(attachmentCount); - AttachmentResourceGuard<Vector<Attachment>, Vector<Attachment>::iterator> attachementDisposer(attachments); RefPtr<WebKit::SharedMemory> oolMessageBody; size_t fdIndex = 0; for (size_t i = 0; i < attachmentCount; ++i) { int fd = -1; - switch (attachmentInfo[i].getType()) { + switch (attachmentInfo[i].type()) { case Attachment::MappedMemoryType: if (!attachmentInfo[i].isNull()) fd = m_fileDescriptors[fdIndex++]; - attachments[attachmentCount - i - 1] = Attachment(fd, attachmentInfo[i].getSize()); + attachments[attachmentCount - i - 1] = Attachment(fd, attachmentInfo[i].size()); break; case Attachment::SocketType: if (!attachmentInfo[i].isNull()) @@ -238,54 +191,53 @@ bool Connection::processMessage() } } - if (messageInfo.isMessageBodyIsOutOfLine()) { + if (messageInfo.isBodyOutOfLine()) { ASSERT(messageInfo.bodySize()); - if (attachmentInfo[attachmentCount].isNull()) { + if (attachmentInfo[attachmentCount].isNull() || attachmentInfo[attachmentCount].size() != messageInfo.bodySize()) { ASSERT_NOT_REACHED(); return false; } WebKit::SharedMemory::Handle handle; - handle.adoptFromAttachment(m_fileDescriptors[attachmentFileDescriptorCount - 1], attachmentInfo[attachmentCount].getSize()); + handle.adoptAttachment(IPC::Attachment(m_fileDescriptors[attachmentFileDescriptorCount - 1], attachmentInfo[attachmentCount].size())); - oolMessageBody = WebKit::SharedMemory::create(handle, WebKit::SharedMemory::ReadOnly); + oolMessageBody = WebKit::SharedMemory::map(handle, WebKit::SharedMemory::Protection::ReadOnly); if (!oolMessageBody) { ASSERT_NOT_REACHED(); return false; } } - ASSERT(attachments.size() == (messageInfo.isMessageBodyIsOutOfLine() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount())); + ASSERT(attachments.size() == (messageInfo.isBodyOutOfLine() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount())); uint8_t* messageBody = messageData; - if (messageInfo.isMessageBodyIsOutOfLine()) + if (messageInfo.isBodyOutOfLine()) messageBody = reinterpret_cast<uint8_t*>(oolMessageBody->data()); - auto decoder = std::make_unique<MessageDecoder>(DataReference(messageBody, messageInfo.bodySize()), std::move(attachments)); + auto decoder = std::make_unique<Decoder>(messageBody, messageInfo.bodySize(), nullptr, WTFMove(attachments)); - processIncomingMessage(std::move(decoder)); + processIncomingMessage(WTFMove(decoder)); - if (m_readBufferSize > messageLength) { - memmove(m_readBuffer.data(), m_readBuffer.data() + messageLength, m_readBufferSize - messageLength); - m_readBufferSize -= messageLength; + if (m_readBuffer.size() > messageLength) { + memmove(m_readBuffer.data(), m_readBuffer.data() + messageLength, m_readBuffer.size() - messageLength); + m_readBuffer.shrink(m_readBuffer.size() - messageLength); } else - m_readBufferSize = 0; + m_readBuffer.shrink(0); if (attachmentFileDescriptorCount) { - if (m_fileDescriptorsSize > attachmentFileDescriptorCount) { - size_t fileDescriptorsLength = attachmentFileDescriptorCount * sizeof(int); - memmove(m_fileDescriptors.data(), m_fileDescriptors.data() + fileDescriptorsLength, m_fileDescriptorsSize - fileDescriptorsLength); - m_fileDescriptorsSize -= fileDescriptorsLength; + if (m_fileDescriptors.size() > attachmentFileDescriptorCount) { + memmove(m_fileDescriptors.data(), m_fileDescriptors.data() + attachmentFileDescriptorCount, (m_fileDescriptors.size() - attachmentFileDescriptorCount) * sizeof(int)); + m_fileDescriptors.shrink(m_fileDescriptors.size() - attachmentFileDescriptorCount); } else - m_fileDescriptorsSize = 0; + m_fileDescriptors.shrink(0); } return true; } -static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int count, int* fileDescriptors, size_t* fileDescriptorsCount) +static ssize_t readBytesFromSocket(int socketDescriptor, Vector<uint8_t>& buffer, Vector<int>& fileDescriptors) { struct msghdr message; memset(&message, 0, sizeof(message)); @@ -294,12 +246,14 @@ static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int co memset(&iov, 0, sizeof(iov)); message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentMaxAmount); - auto attachmentDescriptorBuffer = std::make_unique<char[]>(message.msg_controllen); - memset(attachmentDescriptorBuffer.get(), 0, message.msg_controllen); + MallocPtr<char> attachmentDescriptorBuffer = MallocPtr<char>::malloc(sizeof(char) * message.msg_controllen); + memset(attachmentDescriptorBuffer.get(), 0, sizeof(char) * message.msg_controllen); message.msg_control = attachmentDescriptorBuffer.get(); - iov[0].iov_base = buffer; - iov[0].iov_len = count; + size_t previousBufferSize = buffer.size(); + buffer.grow(buffer.capacity()); + iov[0].iov_base = buffer.data() + previousBufferSize; + iov[0].iov_len = buffer.size() - previousBufferSize; message.msg_iov = iov; message.msg_iovlen = 1; @@ -311,33 +265,33 @@ static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int co if (errno == EINTR) continue; + buffer.shrink(previousBufferSize); 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_SETFD, FD_CLOEXEC) == -1) { - if (errno != EINTR) { - ASSERT_NOT_REACHED(); - break; - } + if (controlMessage->cmsg_len < CMSG_LEN(0) || controlMessage->cmsg_len > attachmentMaxAmount) { + ASSERT_NOT_REACHED(); + break; + } + size_t previousFileDescriptorsSize = fileDescriptors.size(); + size_t fileDescriptorsCount = (controlMessage->cmsg_len - CMSG_LEN(0)) / sizeof(int); + fileDescriptors.grow(fileDescriptors.size() + fileDescriptorsCount); + memcpy(fileDescriptors.data() + previousFileDescriptorsSize, CMSG_DATA(controlMessage), sizeof(int) * fileDescriptorsCount); + + for (size_t i = 0; i < fileDescriptorsCount; ++i) { + if (!setCloseOnExec(fileDescriptors[previousFileDescriptorsSize + i])) { + ASSERT_NOT_REACHED(); + break; } } - - found = true; break; } } - if (!found) - *fileDescriptorsCount = 0; - + buffer.shrink(previousBufferSize + bytesRead); return bytesRead; } @@ -347,24 +301,20 @@ static ssize_t readBytesFromSocket(int socketDescriptor, uint8_t* buffer, int co void Connection::readyReadHandler() { 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); + ssize_t bytesRead = readBytesFromSocket(m_socketDescriptor, m_readBuffer, m_fileDescriptors); if (bytesRead < 0) { // EINTR was already handled by readBytesFromSocket. if (errno == EAGAIN || errno == EWOULDBLOCK) return; - WTFLogAlways("Error receiving IPC message on socket %d in process %d: %s", m_socketDescriptor, getpid(), strerror(errno)); - connectionDidClose(); + if (m_isConnected) { + WTFLogAlways("Error receiving IPC message on socket %d in process %d: %s", m_socketDescriptor, getpid(), strerror(errno)); + connectionDidClose(); + } return; } - m_readBufferSize += bytesRead; - m_fileDescriptorsSize += fileDescriptorsCount; - if (!bytesRead) { connectionDidClose(); return; @@ -388,66 +338,73 @@ bool Connection::open() } } + RefPtr<Connection> protectedThis(this); m_isConnected = true; #if PLATFORM(GTK) - RefPtr<Connection> protector(this); - m_connectionQueue->registerSocketEventHandler(m_socketDescriptor, - [=] { - protector->readyReadHandler(); - }, - [=] { - protector->connectionDidClose(); - }); -#elif PLATFORM(EFL) - RefPtr<Connection> protector(this); - m_connectionQueue->registerSocketEventHandler(m_socketDescriptor, - [protector] { - protector->readyReadHandler(); - }); + m_readSocketMonitor.start(m_socket.get(), G_IO_IN, m_connectionQueue->runLoop(), [protectedThis] (GIOCondition condition) -> gboolean { + if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) { + protectedThis->connectionDidClose(); + return G_SOURCE_REMOVE; + } + + if (condition & G_IO_IN) { + protectedThis->readyReadHandler(); + return G_SOURCE_CONTINUE; + } + + ASSERT_NOT_REACHED(); + return G_SOURCE_REMOVE; + }); #endif - // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal - // handler. - m_connectionQueue->dispatch(WTF::bind(&Connection::readyReadHandler, this)); + // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal handler. + m_connectionQueue->dispatch([protectedThis] { + protectedThis->readyReadHandler(); + }); return true; } bool Connection::platformCanSendOutgoingMessages() const { - return m_isConnected; + return !m_pendingOutputMessage; } -bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) +bool Connection::sendOutgoingMessage(std::unique_ptr<Encoder> encoder) { COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline); - Vector<Attachment> attachments = encoder->releaseAttachments(); - AttachmentResourceGuard<Vector<Attachment>, Vector<Attachment>::iterator> attachementDisposer(attachments); - - if (attachments.size() > (attachmentMaxAmount - 1)) { + UnixMessage outputMessage(*encoder); + if (outputMessage.attachments().size() > (attachmentMaxAmount - 1)) { ASSERT_NOT_REACHED(); return false; } - MessageInfo messageInfo(encoder->bufferSize(), attachments.size()); - size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder->bufferSize(); - if (messageSizeWithBodyInline > messageMaxSize && encoder->bufferSize()) { - RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::create(encoder->bufferSize()); + size_t messageSizeWithBodyInline = sizeof(MessageInfo) + (outputMessage.attachments().size() * sizeof(AttachmentInfo)) + outputMessage.bodySize(); + if (messageSizeWithBodyInline > messageMaxSize && outputMessage.bodySize()) { + RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::allocate(encoder->bufferSize()); if (!oolMessageBody) return false; WebKit::SharedMemory::Handle handle; - if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::ReadOnly)) + if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::Protection::ReadOnly)) return false; - messageInfo.setMessageBodyIsOutOfLine(); + outputMessage.messageInfo().setBodyOutOfLine(); - memcpy(oolMessageBody->data(), encoder->buffer(), encoder->bufferSize()); + memcpy(oolMessageBody->data(), outputMessage.body(), outputMessage.bodySize()); - attachments.append(handle.releaseToAttachment()); + outputMessage.appendAttachment(handle.releaseAttachment()); } + return sendOutputMessage(outputMessage); +} + +bool Connection::sendOutputMessage(UnixMessage& outputMessage) +{ + ASSERT(!m_pendingOutputMessage); + + auto& messageInfo = outputMessage.messageInfo(); struct msghdr message; memset(&message, 0, sizeof(message)); @@ -460,21 +417,21 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) iov[0].iov_base = reinterpret_cast<void*>(&messageInfo); iov[0].iov_len = sizeof(messageInfo); - auto attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size()); - - size_t attachmentFDBufferLength = 0; - if (!attachments.isEmpty()) { - for (size_t i = 0; i < attachments.size(); ++i) { - if (attachments[i].fileDescriptor() != -1) - attachmentFDBufferLength++; - } - } - auto attachmentFDBuffer = std::make_unique<char[]>(CMSG_SPACE(sizeof(int) * attachmentFDBufferLength)); + std::unique_ptr<AttachmentInfo[]> attachmentInfo; + MallocPtr<char> attachmentFDBuffer; + auto& attachments = outputMessage.attachments(); if (!attachments.isEmpty()) { int* fdPtr = 0; + size_t attachmentFDBufferLength = std::count_if(attachments.begin(), attachments.end(), + [](const Attachment& attachment) { + return attachment.fileDescriptor() != -1; + }); + if (attachmentFDBufferLength) { + attachmentFDBuffer = MallocPtr<char>::malloc(sizeof(char) * CMSG_SPACE(sizeof(int) * attachmentFDBufferLength)); + message.msg_control = attachmentFDBuffer.get(); message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentFDBufferLength); memset(message.msg_control, 0, message.msg_controllen); @@ -487,6 +444,7 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) fdPtr = reinterpret_cast<int*>(CMSG_DATA(cmsg)); } + attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size()); int fdIndex = 0; for (size_t i = 0; i < attachments.size(); ++i) { attachmentInfo[i].setType(attachments[i].type()); @@ -513,19 +471,37 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) ++iovLength; } - if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) { - iov[iovLength].iov_base = reinterpret_cast<void*>(encoder->buffer()); - iov[iovLength].iov_len = encoder->bufferSize(); + if (!messageInfo.isBodyOutOfLine() && outputMessage.bodySize()) { + iov[iovLength].iov_base = reinterpret_cast<void*>(outputMessage.body()); + iov[iovLength].iov_len = outputMessage.bodySize(); ++iovLength; } message.msg_iovlen = iovLength; - int bytesSent = 0; - while ((bytesSent = sendmsg(m_socketDescriptor, &message, 0)) == -1) { + while (sendmsg(m_socketDescriptor, &message, 0) == -1) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == EWOULDBLOCK) { +#if PLATFORM(GTK) + m_pendingOutputMessage = std::make_unique<UnixMessage>(WTFMove(outputMessage)); + m_writeSocketMonitor.start(m_socket.get(), G_IO_OUT, m_connectionQueue->runLoop(), [this, protectedThis = makeRef(*this)] (GIOCondition condition) -> gboolean { + if (condition & G_IO_OUT) { + ASSERT(m_pendingOutputMessage); + // We can't stop the monitor from this lambda, because stop destroys the lambda. + m_connectionQueue->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 struct pollfd pollfd; pollfd.fd = m_socketDescriptor; @@ -533,9 +509,11 @@ bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder) pollfd.revents = 0; poll(&pollfd, 1, -1); continue; +#endif } - WTFLogAlways("Error sending IPC message: %s", strerror(errno)); + if (m_isConnected) + WTFLogAlways("Error sending IPC message: %s", strerror(errno)); return false; } return true; @@ -548,18 +526,26 @@ Connection::SocketPair Connection::createPlatformConnection(unsigned options) if (options & SetCloexecOnServer) { // Don't expose the child socket to the parent process. - while (fcntl(sockets[1], F_SETFD, FD_CLOEXEC) == -1) - RELEASE_ASSERT(errno != EINTR); + if (!setCloseOnExec(sockets[1])) + RELEASE_ASSERT_NOT_REACHED(); } if (options & SetCloexecOnClient) { // Don't expose the parent socket to potential future children. - while (fcntl(sockets[0], F_SETFD, FD_CLOEXEC) == -1) - RELEASE_ASSERT(errno != EINTR); + if (!setCloseOnExec(sockets[0])) + RELEASE_ASSERT_NOT_REACHED(); } SocketPair socketPair = { sockets[0], sockets[1] }; return socketPair; } +void Connection::willSendSyncMessage(OptionSet<SendSyncOption>) +{ +} + +void Connection::didReceiveSyncReply(OptionSet<SendSyncOption>) +{ +} + } // namespace IPC diff --git a/Source/WebKit2/Platform/IPC/unix/UnixMessage.h b/Source/WebKit2/Platform/IPC/unix/UnixMessage.h new file mode 100644 index 000000000..6e98a7374 --- /dev/null +++ b/Source/WebKit2/Platform/IPC/unix/UnixMessage.h @@ -0,0 +1,113 @@ +/* + * 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 "Attachment.h" +#include <wtf/Vector.h> + +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& encoder) + : m_attachments(encoder.releaseAttachments()) + , m_messageInfo(encoder.bufferSize(), m_attachments.size()) + , m_body(encoder.buffer()) + { + } + + UnixMessage(UnixMessage&& 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<uint8_t*>(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<Attachment>& attachments() const { return m_attachments; } + MessageInfo& messageInfo() { return m_messageInfo; } + + uint8_t* body() const { return m_body; } + size_t bodySize() const { return m_messageInfo.bodySize(); } + + void appendAttachment(Attachment&& attachment) + { + m_attachments.append(WTFMove(attachment)); + } + +private: + Vector<Attachment> m_attachments; + MessageInfo m_messageInfo; + uint8_t* m_body { nullptr }; + bool m_bodyOwned { false }; +}; + +} // namespace IPC |