Changeset 76507 in webkit


Ignore:
Timestamp:
Jan 24, 2011 4:58:32 AM (13 years ago)
Author:
commit-queue@webkit.org
Message:

2011-01-24 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>

Reviewed by Kenneth Rohde Christiansen.

[Qt] Remove CleanupHandler by passing file descriptors.

Deleting files in signal handler of UI process is not a good idea,
because the memory where filenames are stored might not be valid
after a crash.

To avoid the need of using signal handlers for cleanup,
change following:

1) Avoid passing filenames between processes, pass fds
2) When mmap'ing files, delete them immediately after

opening and mmap'ing them.

3) Pass sockets with fds during fork+exec instead of

passing them via the filesystem.

4) Use mmap'ed files for implementation of SharedMemory.

QSharedMemory does not support cleanup correctly.

Consquences:

  • Move MappedMemory to SharedMemory, make UpdateChunk use this.
  • Implement CoreIPC::Attachment using mmaped files.
  • Send messages using datagram socket. This solution works similiarly to Mach ports on Mac.
  • Send big messages out-of-line and thus avoid increasing the receive buffer.
  • Remove MemoryMappedPool and rely on libc/kernel caching of mmapped areas.
  • Unmap memory areas after use.
  • When UI process crashes, kill the web process using SIGKILL. This is possible again because cleanup handler is not needed.

[WK2][Qt] Multiple problems with MemoryMappedPool
https://bugs.webkit.org/show_bug.cgi?id=51984

  • Platform/CoreIPC/Attachment.cpp: (CoreIPC::Attachment::Attachment):
  • Platform/CoreIPC/Attachment.h: (CoreIPC::Attachment::size): (CoreIPC::Attachment::releaseFileDescriptor): (CoreIPC::Attachment::fileDescriptor):
  • Platform/CoreIPC/Connection.h:
  • Platform/CoreIPC/qt/ConnectionQt.cpp: (CoreIPC::MessageInfo::MessageInfo): (CoreIPC::MessageInfo::setMessageBodyOOL): (CoreIPC::MessageInfo::isMessageBodyOOL): (CoreIPC::MessageInfo::bodySize): (CoreIPC::MessageInfo::messageID): (CoreIPC::MessageInfo::attachmentCount): (CoreIPC::Connection::platformInitialize): (CoreIPC::Connection::platformInvalidate): (CoreIPC::SocketNotifierDisableGuard::SocketNotifierDisableGuard): (CoreIPC::SocketNotifierDisableGuard::~SocketNotifierDisableGuard): (CoreIPC::Connection::readyReadHandler): (CoreIPC::Connection::open): (CoreIPC::Connection::platformCanSendOutgoingMessages): (CoreIPC::Connection::sendOutgoingMessage):
  • Platform/SharedMemory.h:
  • Platform/WorkQueue.h:
  • Platform/qt/MappedMemoryPool.cpp: Removed.
  • Platform/qt/MappedMemoryPool.h: Removed.
  • Platform/qt/SharedMemoryQt.cpp: (WebKit::SharedMemory::Handle::Handle): (WebKit::SharedMemory::Handle::~Handle): (WebKit::SharedMemory::Handle::isNull): (WebKit::SharedMemory::Handle::encode): (WebKit::SharedMemory::Handle::decode): (WebKit::SharedMemory::Handle::releaseToAttachment): (WebKit::SharedMemory::Handle::adoptFromAttachment): (WebKit::SharedMemory::create): (WebKit::accessModeMMap): (WebKit::SharedMemory::~SharedMemory): (WebKit::accessModeFile): (WebKit::SharedMemory::createHandle):
  • Platform/qt/WorkQueueQt.cpp: (WorkQueue::registerSocketEventHandler):
  • Shared/qt/UpdateChunk.cpp: (WebKit::UpdateChunk::UpdateChunk): (WebKit::UpdateChunk::~UpdateChunk): (WebKit::UpdateChunk::encode): (WebKit::UpdateChunk::decode): (WebKit::UpdateChunk::createImage):
  • Shared/qt/UpdateChunk.h:
  • UIProcess/Launcher/ProcessLauncher.h:
  • UIProcess/Launcher/qt/ProcessLauncherQt.cpp: (WebKit::QtWebProcess::QtWebProcess): (WebKit::QtWebProcess::setupChildProcess): (WebKit::ProcessLauncher::launchProcess): (WebKit::ProcessLauncher::platformInvalidate):
  • UIProcess/Launcher/qt/ThreadLauncherQt.cpp: (WebKit::webThreadBody): (WebKit::ThreadLauncher::createWebThread):
  • WebKit2.pro:
  • WebProcess/qt/WebProcessMainQt.cpp: (WebKit::WebProcessMainQt):
Location:
trunk/Source/WebKit2
Files:
2 deleted
19 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r76496 r76507  
     12011-01-24  Kimmo Kinnunen  <kimmo.t.kinnunen@nokia.com>
     2
     3        Reviewed by Kenneth Rohde Christiansen.
     4
     5        [Qt] Remove CleanupHandler by passing file descriptors.
     6
     7        Deleting files in signal handler of UI process is not a good idea,
     8        because the memory where filenames are stored might not be valid
     9        after a crash.
     10
     11        To avoid the need of using signal handlers for cleanup,
     12        change following:
     13          1) Avoid passing filenames between processes, pass fds
     14          2) When mmap'ing files, delete them immediately after
     15             opening and mmap'ing them.
     16          3) Pass sockets with fds during fork+exec instead of
     17             passing them via the filesystem.
     18          4) Use mmap'ed files for implementation of SharedMemory.
     19             QSharedMemory does not support cleanup correctly.
     20
     21        Consquences:
     22          - Move MappedMemory to SharedMemory, make UpdateChunk use this.
     23          - Implement CoreIPC::Attachment using mmaped files.
     24          - Send messages using datagram socket. This solution works
     25            similiarly to Mach ports on Mac.
     26          - Send big messages out-of-line and thus avoid increasing
     27            the receive buffer.
     28          - Remove MemoryMappedPool and rely on libc/kernel caching
     29            of mmapped areas.
     30          - Unmap memory areas after use.
     31          - When UI process crashes, kill the web process using SIGKILL.
     32            This is possible again because cleanup handler is not needed.
     33
     34        [WK2][Qt] Multiple problems with MemoryMappedPool
     35        https://bugs.webkit.org/show_bug.cgi?id=51984
     36
     37        * Platform/CoreIPC/Attachment.cpp:
     38        (CoreIPC::Attachment::Attachment):
     39        * Platform/CoreIPC/Attachment.h:
     40        (CoreIPC::Attachment::size):
     41        (CoreIPC::Attachment::releaseFileDescriptor):
     42        (CoreIPC::Attachment::fileDescriptor):
     43        * Platform/CoreIPC/Connection.h:
     44        * Platform/CoreIPC/qt/ConnectionQt.cpp:
     45        (CoreIPC::MessageInfo::MessageInfo):
     46        (CoreIPC::MessageInfo::setMessageBodyOOL):
     47        (CoreIPC::MessageInfo::isMessageBodyOOL):
     48        (CoreIPC::MessageInfo::bodySize):
     49        (CoreIPC::MessageInfo::messageID):
     50        (CoreIPC::MessageInfo::attachmentCount):
     51        (CoreIPC::Connection::platformInitialize):
     52        (CoreIPC::Connection::platformInvalidate):
     53        (CoreIPC::SocketNotifierDisableGuard::SocketNotifierDisableGuard):
     54        (CoreIPC::SocketNotifierDisableGuard::~SocketNotifierDisableGuard):
     55        (CoreIPC::Connection::readyReadHandler):
     56        (CoreIPC::Connection::open):
     57        (CoreIPC::Connection::platformCanSendOutgoingMessages):
     58        (CoreIPC::Connection::sendOutgoingMessage):
     59        * Platform/SharedMemory.h:
     60        * Platform/WorkQueue.h:
     61        * Platform/qt/MappedMemoryPool.cpp: Removed.
     62        * Platform/qt/MappedMemoryPool.h: Removed.
     63        * Platform/qt/SharedMemoryQt.cpp:
     64        (WebKit::SharedMemory::Handle::Handle):
     65        (WebKit::SharedMemory::Handle::~Handle):
     66        (WebKit::SharedMemory::Handle::isNull):
     67        (WebKit::SharedMemory::Handle::encode):
     68        (WebKit::SharedMemory::Handle::decode):
     69        (WebKit::SharedMemory::Handle::releaseToAttachment):
     70        (WebKit::SharedMemory::Handle::adoptFromAttachment):
     71        (WebKit::SharedMemory::create):
     72        (WebKit::accessModeMMap):
     73        (WebKit::SharedMemory::~SharedMemory):
     74        (WebKit::accessModeFile):
     75        (WebKit::SharedMemory::createHandle):
     76        * Platform/qt/WorkQueueQt.cpp:
     77        (WorkQueue::registerSocketEventHandler):
     78        * Shared/qt/UpdateChunk.cpp:
     79        (WebKit::UpdateChunk::UpdateChunk):
     80        (WebKit::UpdateChunk::~UpdateChunk):
     81        (WebKit::UpdateChunk::encode):
     82        (WebKit::UpdateChunk::decode):
     83        (WebKit::UpdateChunk::createImage):
     84        * Shared/qt/UpdateChunk.h:
     85        * UIProcess/Launcher/ProcessLauncher.h:
     86        * UIProcess/Launcher/qt/ProcessLauncherQt.cpp:
     87        (WebKit::QtWebProcess::QtWebProcess):
     88        (WebKit::QtWebProcess::setupChildProcess):
     89        (WebKit::ProcessLauncher::launchProcess):
     90        (WebKit::ProcessLauncher::platformInvalidate):
     91        * UIProcess/Launcher/qt/ThreadLauncherQt.cpp:
     92        (WebKit::webThreadBody):
     93        (WebKit::ThreadLauncher::createWebThread):
     94        * WebKit2.pro:
     95        * WebProcess/qt/WebProcessMainQt.cpp:
     96        (WebKit::WebProcessMainQt):
     97
    1982011-01-24  Andras Becsi  <abecsi@webkit.org>
    299
  • trunk/Source/WebKit2/Platform/CoreIPC/ArgumentDecoder.cpp

    r68686 r76507  
    4747    ASSERT(m_buffer);
    4848    fastFree(m_buffer);
     49#if !PLATFORM(QT)
    4950    // FIXME: We need to dispose of the mach ports in cases of failure.
     51#else
     52    Deque<Attachment>::iterator end = m_attachments.end();
     53    for (Deque<Attachment>::iterator it = m_attachments.begin(); it != end; ++it)
     54        it->dispose();
     55#endif
    5056}
    5157
  • trunk/Source/WebKit2/Platform/CoreIPC/ArgumentEncoder.cpp

    r71931 r76507  
    5050    if (m_buffer)
    5151        fastFree(m_buffer);
     52#if !PLATFORM(QT)
    5253    // FIXME: We need to dispose of the attachments in cases of failure.
     54#else
     55    for (int i = 0; i < m_attachments.size(); ++i)
     56        m_attachments[i].dispose();
     57#endif
    5358}
    5459
  • trunk/Source/WebKit2/Platform/CoreIPC/Attachment.h

    r64877 r76507  
    4141        MachPortType,
    4242        MachOOLMemoryType
     43#elif PLATFORM(QT)
     44        MappedMemory
    4345#endif
    4446    };
     
    4749    Attachment(mach_port_name_t port, mach_msg_type_name_t disposition);
    4850    Attachment(void* address, mach_msg_size_t size, mach_msg_copy_options_t copyOptions, bool deallocate);
     51#elif PLATFORM(QT)
     52    Attachment(int fileDescriptor, size_t);
    4953#endif
    5054
     
    6367    mach_msg_copy_options_t copyOptions() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.copyOptions; }
    6468    bool deallocate() const { ASSERT(m_type == MachOOLMemoryType); return m_oolMemory.deallocate; }
     69#elif PLATFORM(QT)
     70    size_t size() const { return m_size; }
     71
     72    int releaseFileDescriptor() { int temp = m_fileDescriptor; m_fileDescriptor = -1; return temp; }
     73    int fileDescriptor() const { return m_fileDescriptor; }
     74
     75    void dispose();
    6576#endif
    6677
     
    8495        } m_oolMemory;
    8596    };
     97#elif PLATFORM(QT)
     98    int m_fileDescriptor;
     99    size_t m_size;
    86100#endif
    87101};
  • trunk/Source/WebKit2/Platform/CoreIPC/Connection.h

    r76280 r76507  
    4545#include <string>
    4646#elif PLATFORM(QT)
    47 #include <QString>
    48 class QLocalServer;
    49 class QLocalSocket;
     47class QSocketNotifier;
     48#include "PlatformProcessIdentifier.h"
    5049#endif
    5150
     
    9998    static bool createServerAndClientIdentifiers(Identifier& serverIdentifier, Identifier& clientIdentifier);
    10099#elif PLATFORM(QT)
    101     typedef const QString Identifier;
     100    typedef int Identifier;
    102101#elif PLATFORM(GTK)
    103102    typedef int Identifier;
     
    110109#if PLATFORM(MAC)
    111110    void setShouldCloseConnectionOnMachExceptions();
     111#elif PLATFORM(QT)
     112    void setShouldCloseConnectionOnProcessTermination(WebKit::PlatformProcessIdentifier);
    112113#endif
    113114
     
    286287    Vector<uint8_t> m_readBuffer;
    287288    size_t m_currentMessageSize;
    288     QLocalSocket* m_socket;
    289     QString m_serverName;
     289    QSocketNotifier* m_socketNotifier;
     290    int m_socketDescriptor;
    290291#elif PLATFORM(GTK)
    291292    void readEventHandler();
  • trunk/Source/WebKit2/Platform/CoreIPC/qt/AttachmentQt.cpp

    r76506 r76507  
    11/*
    22 * Copyright (C) 2010 Apple Inc. All rights reserved.
    3  * Copyright (C) 2010 University of Szeged
     3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    1212 *    documentation and/or other materials provided with the distribution.
    1313 *
    14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS AS IS''
     14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
    1515 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    1616 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     
    2525 */
    2626
    27 #include "WebContext.h"
     27#include "Attachment.h"
     28#if PLATFORM(QT)
     29#include <unistd.h>
     30#include <errno.h>
     31#endif
    2832
    29 #include "ApplicationCacheStorage.h"
    30 #include "WebProcessCreationParameters.h"
    3133
    32 namespace WebKit {
     34namespace CoreIPC {
    3335
    34 String WebContext::applicationCacheDirectory()
     36Attachment::Attachment(int fileDescriptor, size_t size)
     37    : m_type(MappedMemory)
     38    , m_fileDescriptor(fileDescriptor)
     39    , m_size(size)
    3540{
    36 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
    37     return WebCore::cacheStorage().cacheDirectory();
    38 #else
    39     return QString();
    40 #endif
     41    ASSERT(m_fileDescriptor);
     42    ASSERT(m_size);
    4143}
    4244
    43 void WebContext::platformInitializeWebProcess(WebProcessCreationParameters&)
     45void Attachment::dispose()
    4446{
     47    if (m_fileDescriptor != -1)
     48        while (close(m_fileDescriptor) == -1 && (errno == EINTR)) { }
    4549}
    4650
    47 } // namespace WebKit
     51} // namespace CoreIPC
  • trunk/Source/WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp

    r74967 r76507  
    3030#include "ProcessLauncher.h"
    3131#include "WorkItem.h"
     32#include "SharedMemory.h"
     33#include "WebProcessProxy.h"
    3234#include <QApplication>
    33 #include <QLocalServer>
    34 #include <QLocalSocket>
     35#include <QSocketNotifier>
     36#include <sys/socket.h>
     37#include <unistd.h>
     38#include <errno.h>
     39#include <fcntl.h>
     40#include <wtf/Assertions.h>
    3541
    3642using namespace std;
     
    3844namespace CoreIPC {
    3945
    40 // This is what other ports use...
    4146static const size_t messageMaxSize = 4096;
     47static const size_t attachmentMaxAmount = 255;
     48
     49enum {
     50    MessageBodyIsOOL = 1 << 31
     51};
     52
     53class MessageInfo {
     54public:
     55    MessageInfo() { }
     56
     57    MessageInfo(MessageID messageID, size_t bodySize, size_t initialAttachmentCount)
     58        : m_messageID(messageID.toInt())
     59        , m_bodySize(bodySize)
     60        , m_attachmentCount(initialAttachmentCount)
     61    {
     62        ASSERT(!(m_messageID & MessageBodyIsOOL));
     63    }
     64
     65    void setMessageBodyOOL()
     66    {
     67        ASSERT(!isMessageBodyOOL());
     68
     69        m_messageID |= MessageBodyIsOOL;
     70        m_attachmentCount++;
     71    }
     72
     73    bool isMessageBodyOOL() const { return m_messageID & MessageBodyIsOOL; }
     74
     75    size_t bodySize() const { return m_bodySize; }
     76
     77    MessageID messageID() const { return MessageID::fromInt(m_messageID & ~MessageBodyIsOOL); }
     78
     79    size_t attachmentCount() const { return m_attachmentCount; }
     80
     81private:
     82    uint32_t m_messageID;
     83    size_t m_bodySize;
     84    size_t m_attachmentCount;
     85};
    4286
    4387void Connection::platformInitialize(Identifier identifier)
    4488{
    45     m_serverName = identifier;
    46     m_socket = 0;
     89    m_socketDescriptor = identifier;
     90    m_socketNotifier = 0;
    4791    m_readBuffer.resize(messageMaxSize);
    4892    m_currentMessageSize = 0;
     
    5195void Connection::platformInvalidate()
    5296{
    53     m_socket->disconnect();
    54     if (!m_isServer)
    55         m_socket->deleteLater();
    56     m_socket = 0;
    57 }
     97    if (m_socketDescriptor != -1)
     98        while (close(m_socketDescriptor) == -1 && errno == EINTR) { }
     99
     100    if (!m_isConnected)
     101        return;
     102
     103    delete m_socketNotifier;
     104    m_socketNotifier = 0;
     105    m_socketDescriptor = -1;
     106    m_isConnected = false;
     107}
     108
     109class SocketNotifierResourceGuard {
     110public:
     111    SocketNotifierResourceGuard(QSocketNotifier* socketNotifier)
     112        : m_socketNotifier(socketNotifier)
     113    {
     114        m_socketNotifier->setEnabled(false);
     115    }
     116
     117    ~SocketNotifierResourceGuard()
     118    {
     119        m_socketNotifier->setEnabled(true);
     120    }
     121
     122private:
     123    QSocketNotifier* const m_socketNotifier;
     124};
     125
     126template<class T, class iterator>
     127class AttachmentResourceGuard {
     128public:
     129    AttachmentResourceGuard(T& attachments)
     130        : m_attachments(attachments)
     131    {
     132    }
     133    ~AttachmentResourceGuard()
     134    {
     135        iterator end = m_attachments.end();
     136        for (iterator i = m_attachments.begin(); i != end; ++i)
     137            i->dispose();
     138    }
     139private:
     140    T& m_attachments;
     141};
    58142
    59143void Connection::readyReadHandler()
    60144{
    61     while (m_socket->bytesAvailable()) {
    62         if (!m_currentMessageSize) {
    63             size_t numberOfBytesRead = m_socket->read(reinterpret_cast<char*>(m_readBuffer.data()), sizeof(size_t));
    64             ASSERT_UNUSED(numberOfBytesRead, numberOfBytesRead);
    65             m_currentMessageSize = *reinterpret_cast<size_t*>(m_readBuffer.data());
     145    Deque<Attachment> attachments;
     146    SocketNotifierResourceGuard socketNotifierEnabler(m_socketNotifier);
     147    AttachmentResourceGuard<Deque<Attachment>, Deque<Attachment>::iterator> attachementDisposer(attachments);
     148
     149    char attachmentDescriptorBuffer[CMSG_SPACE(sizeof(int) * (attachmentMaxAmount))];
     150    struct msghdr message;
     151    memset(&message, 0, sizeof(message));
     152
     153    struct iovec iov[1];
     154    memset(&iov, 0, sizeof(iov));
     155
     156    message.msg_control = attachmentDescriptorBuffer;
     157    message.msg_controllen = CMSG_SPACE(sizeof(int) * (attachmentMaxAmount));
     158
     159    iov[0].iov_base = m_readBuffer.data();
     160    iov[0].iov_len = m_readBuffer.size();
     161
     162    message.msg_iov = iov;
     163    message.msg_iovlen = 1;
     164
     165
     166    int messageLength = 0;
     167    while ((messageLength = recvmsg(m_socketDescriptor, &message, MSG_CMSG_CLOEXEC)) == -1) {
     168        if (errno != EINTR)
     169            return;
     170    }
     171
     172    struct cmsghdr* controlMessage = CMSG_FIRSTHDR(&message);
     173
     174    MessageInfo messageInfo;
     175    unsigned char* messageData = m_readBuffer.data();
     176
     177    memcpy(&messageInfo, messageData, sizeof(messageInfo));
     178    ASSERT(messageLength == sizeof(messageInfo) + messageInfo.attachmentCount() * sizeof(size_t) + (messageInfo.isMessageBodyOOL() ? 0 : messageInfo.bodySize()));
     179
     180    messageData += sizeof(messageInfo);
     181
     182    RefPtr<WebKit::SharedMemory> oolMessageBody;
     183
     184    if (messageInfo.attachmentCount()) {
     185        if (controlMessage && controlMessage->cmsg_level == SOL_SOCKET && controlMessage->cmsg_type == SCM_RIGHTS) {
     186            size_t attachmentSizes[messageInfo.attachmentCount()];
     187            memcpy(attachmentSizes, messageData, sizeof(attachmentSizes));
     188
     189            messageData += sizeof(attachmentSizes);
     190
     191            int fileDescriptors[messageInfo.attachmentCount()];
     192            memcpy(fileDescriptors, CMSG_DATA(controlMessage), sizeof(fileDescriptors));
     193
     194            int attachmentCount = messageInfo.attachmentCount();
     195
     196            if (messageInfo.isMessageBodyOOL())
     197                attachmentCount--;
     198
     199            for (int i = 0; i < attachmentCount; ++i)
     200                attachments.append(Attachment(fileDescriptors[i], attachmentSizes[i]));
     201
     202            if (messageInfo.isMessageBodyOOL()) {
     203                ASSERT(messageInfo.bodySize());
     204
     205                WebKit::SharedMemory::Handle handle;
     206                handle.adoptFromAttachment(fileDescriptors[attachmentCount], attachmentSizes[attachmentCount]);
     207                if (handle.isNull()) {
     208                    ASSERT_NOT_REACHED();
     209                    return;
     210                }
     211
     212                oolMessageBody = WebKit::SharedMemory::create(handle, WebKit::SharedMemory::ReadOnly);
     213                if (!oolMessageBody) {
     214                    ASSERT_NOT_REACHED();
     215                    return;
     216                }
     217            }
     218
     219            controlMessage = CMSG_NXTHDR(&message, controlMessage);
     220        } else {
     221            ASSERT_NOT_REACHED();
     222            return;
    66223        }
    67 
    68         if (m_socket->bytesAvailable() < m_currentMessageSize)
    69             return;
    70 
    71         if (m_readBuffer.size() < m_currentMessageSize)
    72             m_readBuffer.grow(m_currentMessageSize);
    73 
    74         size_t numberOfBytesRead = m_socket->read(reinterpret_cast<char*>(m_readBuffer.data()), m_currentMessageSize);
    75         ASSERT_UNUSED(numberOfBytesRead, numberOfBytesRead);
    76 
    77         // The messageID is encoded at the end of the buffer.
    78         size_t realBufferSize = m_currentMessageSize - sizeof(uint32_t);
    79         uint32_t messageID = *reinterpret_cast<uint32_t*>(m_readBuffer.data() + realBufferSize);
    80 
    81         processIncomingMessage(MessageID::fromInt(messageID), adoptPtr(new ArgumentDecoder(m_readBuffer.data(), realBufferSize)));
    82 
    83         m_currentMessageSize = 0;
    84     }
     224    }
     225
     226    ASSERT(attachments.size() == messageInfo.isMessageBodyOOL() ? messageInfo.attachmentCount() - 1 : messageInfo.attachmentCount());
     227
     228    unsigned char* messageBody = messageData;
     229
     230    if (messageInfo.isMessageBodyOOL())
     231        messageBody = reinterpret_cast<unsigned char*>(oolMessageBody->data());
     232
     233    ArgumentDecoder* argumentDecoder;
     234    if (attachments.isEmpty())
     235        argumentDecoder = new ArgumentDecoder(messageBody, messageInfo.bodySize());
     236    else
     237        argumentDecoder = new ArgumentDecoder(messageBody, messageInfo.bodySize(), attachments);
     238
     239    processIncomingMessage(messageInfo.messageID(), adoptPtr(argumentDecoder));
     240
     241    ASSERT(!controlMessage);
    85242}
    86243
    87244bool Connection::open()
    88245{
    89     ASSERT(!m_socket);
    90 
    91     if (m_isServer) {
    92         m_socket = WebKit::ProcessLauncher::takePendingConnection();
    93         m_isConnected = m_socket;
    94         if (m_isConnected) {
    95             m_connectionQueue.moveSocketToWorkThread(m_socket);
    96             m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
     246    ASSERT(!m_socketNotifier);
     247    int flags = fcntl(m_socketDescriptor, F_GETFL, 0);
     248    while (fcntl(m_socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
     249        if (errno != EINTR) {
     250            ASSERT_NOT_REACHED();
     251            return false;
    97252        }
    98     } else {
    99         m_socket = new QLocalSocket();
    100         m_socket->connectToServer(m_serverName);
    101         m_connectionQueue.moveSocketToWorkThread(m_socket);
    102         m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
    103         m_connectionQueue.connectSignal(m_socket, SIGNAL(disconnected()), WorkItem::create(this, &Connection::connectionDidClose));
    104         m_isConnected = m_socket->waitForConnected();
    105     }
    106     return m_isConnected;
     253    }
     254
     255    m_isConnected = true;
     256    m_socketNotifier = m_connectionQueue.registerSocketEventHandler(m_socketDescriptor, QSocketNotifier::Read, WorkItem::create(this, &Connection::readyReadHandler));
     257
     258    // Schedule a call to readyReadHandler. Data may have arrived before installation of the signal
     259    // handler.
     260    m_connectionQueue.scheduleWork(WorkItem::create(this, &Connection::readyReadHandler));
     261
     262    return true;
    107263}
    108264
    109265bool Connection::platformCanSendOutgoingMessages() const
    110266{
    111     return m_socket;
     267    return m_socketNotifier;
    112268}
    113269
    114270bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<ArgumentEncoder> arguments)
    115271{
    116     ASSERT(m_socket);
    117 
    118     // We put the message ID last.
    119     arguments->encodeUInt32(messageID.toInt());
    120 
    121     size_t bufferSize = arguments->bufferSize();
    122 
    123     // Write message size first
    124     // FIXME: Should  just do a single write.
    125     qint64 bytesWrittenForSize = m_socket->write(reinterpret_cast<char*>(&bufferSize), sizeof(bufferSize));
    126     if (bytesWrittenForSize != sizeof(bufferSize)) {
    127         connectionDidClose();
     272    ASSERT(m_socketNotifier);
     273    COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline);
     274
     275    Vector<Attachment> attachments = arguments->releaseAttachments();
     276    AttachmentResourceGuard<Vector<Attachment>, Vector<Attachment>::iterator> attachementDisposer(attachments);
     277
     278    if (attachments.size() > (attachmentMaxAmount - 1)) {
     279        ASSERT_NOT_REACHED();
    128280        return false;
    129281    }
    130282
    131     qint64 bytesWrittenForBuffer = m_socket->write(reinterpret_cast<char*>(arguments->buffer()), arguments->bufferSize());
    132     if (bytesWrittenForBuffer != arguments->bufferSize()) {
    133         connectionDidClose();
    134         return false;
    135     }
    136 
    137     m_socket->flush();
    138 
     283    MessageInfo messageInfo(messageID, arguments->bufferSize(), attachments.size());
     284    size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(size_t)) + arguments->bufferSize();
     285    if (messageSizeWithBodyInline > messageMaxSize && arguments->bufferSize()) {
     286        RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::create(arguments->bufferSize());
     287        if (!oolMessageBody)
     288            return false;
     289
     290        WebKit::SharedMemory::Handle handle;
     291        if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::ReadOnly))
     292            return false;
     293
     294        messageInfo.setMessageBodyOOL();
     295
     296        memcpy(oolMessageBody->data(), arguments->buffer(), arguments->bufferSize());
     297
     298        attachments.append(handle.releaseToAttachment());
     299    }
     300
     301    struct msghdr message;
     302    memset(&message, 0, sizeof(message));
     303
     304    struct iovec iov[3];
     305    memset(&iov, 0, sizeof(iov));
     306
     307    message.msg_iov = iov;
     308    int iovLength = 1;
     309
     310    iov[0].iov_base = reinterpret_cast<void*>(&messageInfo);
     311    iov[0].iov_len = sizeof(messageInfo);
     312
     313    char attachmentFDBuffer[CMSG_SPACE(sizeof(int) * (attachments.size()))];
     314    size_t attachmentSizes[attachments.size()];
     315
     316    if (!attachments.isEmpty()) {
     317        message.msg_control = attachmentFDBuffer;
     318        message.msg_controllen = sizeof(attachmentFDBuffer);
     319
     320        struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message);
     321        cmsg->cmsg_level = SOL_SOCKET;
     322        cmsg->cmsg_type = SCM_RIGHTS;
     323        cmsg->cmsg_len = CMSG_LEN(sizeof(int) * attachments.size());
     324
     325        int* fdptr = reinterpret_cast<int*>(CMSG_DATA(cmsg));
     326        for (int i = 0; i < attachments.size(); ++i) {
     327            attachmentSizes[i] = attachments[i].size();
     328            fdptr[i] = attachments[i].fileDescriptor();
     329        }
     330
     331        message.msg_controllen = cmsg->cmsg_len;
     332
     333        iov[iovLength].iov_base = attachmentSizes;
     334        iov[iovLength].iov_len = sizeof(attachmentSizes);
     335        ++iovLength;
     336    }
     337
     338    if (!messageInfo.isMessageBodyOOL() && arguments->bufferSize()) {
     339        iov[iovLength].iov_base = reinterpret_cast<void*>(arguments->buffer());
     340        iov[iovLength].iov_len = arguments->bufferSize();
     341        ++iovLength;
     342    }
     343
     344    message.msg_iovlen = iovLength;
     345
     346    int bytesSent = 0;
     347    while ((bytesSent = sendmsg(m_socketDescriptor, &message, 0)) == -1) {
     348        if (errno != EINTR)
     349            return false;
     350    }
    139351    return true;
    140352}
    141353
     354void Connection::setShouldCloseConnectionOnProcessTermination(WebKit::PlatformProcessIdentifier process)
     355{
     356    m_connectionQueue.scheduleWorkOnTermination(process, WorkItem::create(this, &Connection::connectionDidClose));
     357}
     358
    142359} // namespace CoreIPC
  • trunk/Source/WebKit2/Platform/SharedMemory.h

    r76248 r76507  
    3232
    3333#if PLATFORM(QT)
    34 #include <QtGlobal>
    35 QT_BEGIN_NAMESPACE
    36 class QSharedMemory;
    37 QT_END_NAMESPACE
     34#include "Attachment.h"
    3835#include <wtf/text/WTFString.h>
    3936#endif
     
    6461        static bool decode(CoreIPC::ArgumentDecoder*, Handle&);
    6562
     63#if PLATFORM(QT)
     64        CoreIPC::Attachment releaseToAttachment() const;
     65        void adoptFromAttachment(int fileDescriptor, size_t);
     66#endif
    6667    private:
    6768        friend class SharedMemory;
     
    7172        mutable HANDLE m_handle;
    7273#elif PLATFORM(QT)
    73         mutable String m_key;
     74        mutable int m_fileDescriptor;
    7475#endif
    7576        size_t m_size;
     
    9899    HANDLE m_handle;
    99100#elif PLATFORM(QT)
    100     QSharedMemory* m_impl;
     101    int m_fileDescriptor;
    101102#endif
    102103};
  • trunk/Source/WebKit2/Platform/WorkQueue.h

    r73142 r76507  
    4242
    4343#if PLATFORM(QT)
    44 class QLocalSocket;
     44#include <QSocketNotifier>
     45#include "PlatformProcessIdentifier.h"
    4546class QObject;
    4647class QThread;
     
    8081    void unregisterAndCloseHandle(HANDLE);
    8182#elif PLATFORM(QT)
    82     void connectSignal(QObject*, const char* signal, PassOwnPtr<WorkItem>);
    83     void disconnectSignal(QObject*, const char* signal);
    84 
    85     void moveSocketToWorkThread(QLocalSocket*);
     83    QSocketNotifier* registerSocketEventHandler(int, QSocketNotifier::Type, PassOwnPtr<WorkItem>);
     84    void scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier, PassOwnPtr<WorkItem>);
    8685#elif PLATFORM(GTK)
    8786    void registerEventSourceHandler(int, int, PassOwnPtr<WorkItem>);
  • trunk/Source/WebKit2/Platform/qt/SharedMemoryQt.cpp

    r75935 r76507  
    3030#include "ArgumentDecoder.h"
    3131#include "ArgumentEncoder.h"
    32 #include "CleanupHandler.h"
    3332#include "WebCoreArgumentCoders.h"
     33#include <QDir>
     34#include <errno.h>
     35#include <fcntl.h>
     36#include <stdlib.h>
     37#include <sys/mman.h>
     38#include <sys/stat.h>
     39#include <sys/types.h>
    3440#include <unistd.h>
    35 #include <QCoreApplication>
    36 #include <QLatin1String>
    37 #include <QSharedMemory>
    38 #include <QString>
    39 #include <QUuid>
    4041#include <wtf/Assertions.h>
    4142#include <wtf/CurrentTime.h>
     
    4445
    4546SharedMemory::Handle::Handle()
    46     : m_key()
     47    : m_fileDescriptor(-1)
    4748    , m_size(0)
    4849{
     
    5152SharedMemory::Handle::~Handle()
    5253{
     54    if (!isNull())
     55        while (close(m_fileDescriptor) == -1 && errno == EINTR) { }
    5356}
    5457
    5558bool SharedMemory::Handle::isNull() const
    5659{
    57     return m_key.isNull();
     60    return m_fileDescriptor == -1;
    5861}
    5962
    6063void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
    6164{
    62     encoder->encodeUInt64(m_size);
    63     encoder->encode(m_key);
    64     m_key = String();
     65    ASSERT(!isNull());
     66
     67    encoder->encode(releaseToAttachment());
    6568}
    6669
     
    6871{
    6972    ASSERT_ARG(handle, !handle.m_size);
    70     ASSERT_ARG(handle, handle.m_key.isNull());
    71 
    72     uint64_t size;
    73     if (!decoder->decodeUInt64(size))
     73    ASSERT_ARG(handle, handle.isNull());
     74
     75    CoreIPC::Attachment attachment;
     76    if (!decoder->decode(attachment))
    7477        return false;
    7578
    76     String key;
    77     if (!decoder->decode(key))
    78        return false;
    79 
    80     handle.m_size = size;
    81     handle.m_key = key;
    82 
     79    handle.adoptFromAttachment(attachment.releaseFileDescriptor(), attachment.size());
    8380    return true;
    8481}
    8582
    86 static QString createUniqueKey()
    87 {
    88     return QLatin1String("QWKSharedMemoryKey") + QUuid::createUuid().toString();
     83CoreIPC::Attachment SharedMemory::Handle::releaseToAttachment() const
     84{
     85    ASSERT(!isNull());
     86
     87    int temp = m_fileDescriptor;
     88    m_fileDescriptor = -1;
     89    return CoreIPC::Attachment(temp, m_size);
     90}
     91
     92void SharedMemory::Handle::adoptFromAttachment(int fileDescriptor, size_t size)
     93{
     94    ASSERT(!m_size);
     95    ASSERT(isNull());
     96
     97    m_fileDescriptor = fileDescriptor;
     98    m_size = size;
    8999}
    90100
    91101PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
    92102{
    93     RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory));
    94     QSharedMemory* impl = new QSharedMemory(createUniqueKey());
    95     bool created = impl->create(size);
    96     ASSERT_UNUSED(created, created);
    97 
    98     sharedMemory->m_impl = impl;
    99     sharedMemory->m_size = size;
    100     sharedMemory->m_data = impl->data();
    101 
    102     // Do not leave the shared memory segment behind.
    103     CleanupHandler::instance()->markForCleanup(impl);
    104 
    105     return sharedMemory.release();
    106 }
    107 
    108 static inline QSharedMemory::AccessMode accessMode(SharedMemory::Protection protection)
     103    QString tempName = QDir::temp().filePath("qwkshm.XXXXXX");
     104    QByteArray tempNameCSTR = tempName.toLocal8Bit();
     105    char* tempNameC = tempNameCSTR.data();
     106
     107    int fileDescriptor;
     108    while ((fileDescriptor = mkostemp(tempNameC, O_CREAT | O_CLOEXEC | O_RDWR)) == -1) {
     109        if (errno != EINTR)
     110            return 0;
     111    }
     112
     113    while (ftruncate(fileDescriptor, size) == -1) {
     114        if (errno != EINTR) {
     115            while (close(fileDescriptor) == -1 && errno == EINTR) { }
     116            unlink(tempNameC);
     117            return 0;
     118        }
     119    }
     120
     121    void* data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileDescriptor, 0);
     122    if (data == MAP_FAILED) {
     123        while (close(fileDescriptor) == -1 && errno == EINTR) { }
     124        unlink(tempNameC);
     125        return 0;
     126    }
     127
     128    unlink(tempNameC);
     129
     130    RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
     131    instance->m_data = data;
     132    instance->m_fileDescriptor = fileDescriptor;
     133    instance->m_size = size;
     134    return instance.release();
     135}
     136
     137static inline int accessModeMMap(SharedMemory::Protection protection)
    109138{
    110139    switch (protection) {
    111140    case SharedMemory::ReadOnly:
    112         return QSharedMemory::ReadOnly;
     141        return PROT_READ;
    113142    case SharedMemory::ReadWrite:
    114         return QSharedMemory::ReadWrite;
     143        return PROT_READ | PROT_WRITE;
    115144    }
    116145
    117146    ASSERT_NOT_REACHED();
    118     return QSharedMemory::ReadWrite;
     147    return PROT_READ | PROT_WRITE;
    119148}
    120149
    121150PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
    122151{
    123     if (handle.isNull())
     152    ASSERT(!handle.isNull());
     153
     154    void* data = mmap(0, handle.m_size, accessModeMMap(protection), MAP_SHARED, handle.m_fileDescriptor, 0);
     155    if (data == MAP_FAILED)
    124156        return 0;
    125157
    126     QSharedMemory* impl = new QSharedMemory(QString(handle.m_key));
    127     bool attached = impl->attach(accessMode(protection));
    128     if (!attached) {
    129         delete impl;
    130         return 0;
    131     }
    132 
    133     RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory));
    134     sharedMemory->m_impl = impl;
    135     ASSERT(handle.m_size == impl->size());
    136     sharedMemory->m_size = handle.m_size;
    137     sharedMemory->m_data = impl->data();
    138 
    139     // Do not leave the shared memory segment behind.
    140     CleanupHandler::instance()->markForCleanup(impl);
    141 
    142     return sharedMemory.release();
     158    RefPtr<SharedMemory> instance = adoptRef(new SharedMemory());
     159    instance->m_data = data;
     160    instance->m_fileDescriptor = handle.m_fileDescriptor;
     161    instance->m_size = handle.m_size;
     162    handle.m_fileDescriptor = -1;
     163    return instance;
    143164}
    144165
    145166SharedMemory::~SharedMemory()
    146167{
    147     if (CleanupHandler::instance()->hasStartedDeleting())
    148         return;
    149 
    150     CleanupHandler::instance()->unmark(m_impl);
    151     delete m_impl;
     168    munmap(m_data, m_size);
     169    while (close(m_fileDescriptor) == -1 && errno == EINTR) { }
     170}
     171
     172static inline int accessModeFile(SharedMemory::Protection protection)
     173{
     174    switch (protection) {
     175    case SharedMemory::ReadOnly:
     176        return O_RDONLY;
     177    case SharedMemory::ReadWrite:
     178        return O_RDWR;
     179    }
     180
     181    ASSERT_NOT_REACHED();
     182    return O_RDWR;
    152183}
    153184
    154185bool SharedMemory::createHandle(Handle& handle, Protection protection)
    155186{
    156     ASSERT_ARG(handle, handle.m_key.isNull());
    157187    ASSERT_ARG(handle, !handle.m_size);
    158 
    159     QString key = m_impl->key();
    160     if (key.isNull())
    161         return false;
    162     handle.m_key = String(key);
     188    ASSERT_ARG(handle, handle.isNull());
     189
     190    int duplicatedHandle;
     191    while ((duplicatedHandle = dup(m_fileDescriptor)) == -1) {
     192        if (errno != EINTR) {
     193            ASSERT_NOT_REACHED();
     194            return false;
     195        }
     196    }
     197
     198    while ((fcntl(duplicatedHandle, F_SETFD,  O_CLOEXEC | accessModeFile(protection)) == -1)) {
     199        if (errno != EINTR) {
     200            ASSERT_NOT_REACHED();
     201            while (close(duplicatedHandle) == -1 && errno == EINTR) { }
     202            return false;
     203        }
     204    }
     205    handle.m_fileDescriptor = duplicatedHandle;
    163206    handle.m_size = m_size;
    164 
    165207    return true;
    166208}
  • trunk/Source/WebKit2/Platform/qt/WorkQueueQt.cpp

    r71456 r76507  
    3030#include <QObject>
    3131#include <QThread>
     32#include <QProcess>
    3233#include <wtf/Threading.h>
    3334#include "NotImplemented.h"
     
    7677};
    7778
    78 void WorkQueue::connectSignal(QObject* o, const char* signal, PassOwnPtr<WorkItem> workItem)
    79 {
    80     WorkQueue::WorkItemQt* itemQt = new WorkQueue::WorkItemQt(this, o, signal, workItem.leakPtr());
    81     itemQt->moveToThread(m_workThread);
    82     m_signalListeners.add(o, itemQt);
    83 }
    84 
    85 void WorkQueue::disconnectSignal(QObject* o, const char* name)
    86 {
    87     HashMap<QObject*, WorkItemQt*>::iterator it = m_signalListeners.find(o);
    88     for (; it != m_signalListeners.end(); ++it) {
    89         if (strcmp(it->second->m_signal, name))
    90             continue;
    91         delete it->second;
    92         m_signalListeners.remove(it);
    93         return;
    94     }
    95 }
    96 
    97 void WorkQueue::moveSocketToWorkThread(QLocalSocket* socket)
     79QSocketNotifier* WorkQueue::registerSocketEventHandler(int socketDescriptor, QSocketNotifier::Type type, PassOwnPtr<WorkItem> workItem)
    9880{
    9981    ASSERT(m_workThread);
    100     ASSERT(socket);
    10182
    102     socket->setParent(0);
    103     socket->moveToThread(m_workThread);
     83    QSocketNotifier* notifier = new QSocketNotifier(socketDescriptor, type, 0);
     84    notifier->setEnabled(false);
     85    notifier->moveToThread(m_workThread);
     86    WorkQueue::WorkItemQt* itemQt = new WorkQueue::WorkItemQt(this, notifier, SIGNAL(activated(int)), workItem.leakPtr());
     87    itemQt->moveToThread(m_workThread);
     88    notifier->setEnabled(true);
     89    return notifier;
    10490}
    10591
     
    130116}
    131117
     118void WorkQueue::scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier process, PassOwnPtr<WorkItem> workItem)
     119{
     120    WorkQueue::WorkItemQt* itemQt = new WorkQueue::WorkItemQt(this, process, SIGNAL(finished(int, QProcess::ExitStatus)), workItem.leakPtr());
     121    itemQt->moveToThread(m_workThread);
     122}
     123
    132124#include "WorkQueueQt.moc"
  • trunk/Source/WebKit2/Shared/qt/UpdateChunk.cpp

    r72185 r76507  
    3030#include "ArgumentDecoder.h"
    3131#include "ArgumentEncoder.h"
    32 #include "MappedMemoryPool.h"
    3332#include "WebCoreArgumentCoders.h"
    3433#include <QIODevice>
     
    4443
    4544UpdateChunk::UpdateChunk()
    46     : m_mappedMemory(0)
    4745{
    4846}
     
    5048UpdateChunk::UpdateChunk(const IntRect& rect)
    5149    : m_rect(rect)
    52     , m_mappedMemory(MappedMemoryPool::instance()->mapMemory(size()))
     50    , m_sharedMemory(SharedMemory::create(size()))
    5351{
    5452}
     
    5654UpdateChunk::~UpdateChunk()
    5755{
    58     if (m_mappedMemory)
    59         m_mappedMemory->markFree();
    6056}
    6157
     
    6359{
    6460    encoder->encode(m_rect);
    65     encoder->encode(String(m_mappedMemory->mappedFileName()));
     61    if (!m_sharedMemory) {
     62        encoder->encode(false);
     63        return;
     64    }
    6665
    67     m_mappedMemory = 0;
     66    SharedMemory::Handle handle;
     67    if (m_sharedMemory->createHandle(handle, SharedMemory::ReadOnly)) {
     68        encoder->encode(true);
     69        encoder->encode(handle);
     70    } else
     71        encoder->encode(false);
     72
     73    m_sharedMemory = 0;
    6874}
    6975
     
    7581    if (!decoder->decode(rect))
    7682        return false;
     83
    7784    chunk.m_rect = rect;
    7885
    79     if (chunk.isEmpty())
    80         return true; // Successfully decoded empty chunk.
    81 
    82     String fileName;
    83     if (!decoder->decode(fileName))
     86    bool hasSharedMemory;
     87    if (!decoder->decode(hasSharedMemory))
    8488        return false;
    8589
    86     chunk.m_mappedMemory = MappedMemoryPool::instance()->mapFile(fileName, chunk.size());
     90    if (!hasSharedMemory) {
     91        chunk.m_sharedMemory = 0;
     92        return true;
     93    }
     94
     95    SharedMemory::Handle handle;
     96    if (!decoder->decode(handle))
     97        return false;
     98
     99    chunk.m_sharedMemory = SharedMemory::create(handle, SharedMemory::ReadOnly);
    87100    return true;
    88101}
     
    102115QImage UpdateChunk::createImage() const
    103116{
    104     ASSERT(m_mappedMemory);
     117    ASSERT(m_sharedMemory);
     118    if (!m_sharedMemory)
     119        return QImage();
     120
    105121    QImage::Format format;
    106122    int bpp;
     
    113129    }
    114130
    115     return QImage(m_mappedMemory->data(), m_rect.width(), m_rect.height(), (m_rect.width() * bpp + 3) & ~0x3, format);
     131    return QImage(reinterpret_cast<unsigned char*>(m_sharedMemory->data()), m_rect.width(), m_rect.height(), (m_rect.width() * bpp + 3) & ~0x3, format);
    116132}
    117133
  • trunk/Source/WebKit2/Shared/qt/UpdateChunk.h

    r72185 r76507  
    3030#include <QImage>
    3131#include <WebCore/IntRect.h>
     32#include "SharedMemory.h"
    3233
    3334namespace CoreIPC {
     
    3738
    3839namespace WebKit {
    39 
    40 class MappedMemory;
    4140
    4241class UpdateChunk {
     
    5958    WebCore::IntRect m_rect;
    6059
    61     mutable MappedMemory* m_mappedMemory;
     60    mutable RefPtr<SharedMemory> m_sharedMemory;
    6261};
    6362
  • trunk/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h

    r68391 r76507  
    7373    static bool getProcessTypeFromString(const char*, ProcessType&);
    7474
    75 #if PLATFORM(QT)
    76     friend class ProcessLauncherHelper;
    77     static QLocalSocket* takePendingConnection();
    78 #endif
    79 
    8075private:
    8176    ProcessLauncher(Client*, const LaunchOptions& launchOptions);
  • trunk/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp

    r74967 r76507  
    2828
    2929#include "Connection.h"
    30 #include "CleanupHandler.h"
    3130#include "NotImplemented.h"
    3231#include "RunLoop.h"
    3332#include "WebProcess.h"
    34 #include <runtime/InitializeThreading.h>
    35 #include <string>
    36 #include <wtf/HashSet.h>
    37 #include <wtf/PassRefPtr.h>
    38 #include <wtf/Threading.h>
    39 #include <wtf/text/WTFString.h>
    40 
    4133#include <QApplication>
    4234#include <QDebug>
     
    4638#include <QProcess>
    4739#include <QString>
    48 
    4940#include <QtCore/qglobal.h>
    50 
     41#include <errno.h>
     42#include <fcntl.h>
     43#include <runtime/InitializeThreading.h>
     44#include <string>
    5145#include <sys/resource.h>
     46#include <sys/socket.h>
    5247#include <unistd.h>
     48#include <wtf/HashSet.h>
     49#include <wtf/PassRefPtr.h>
     50#include <wtf/Threading.h>
     51#include <wtf/text/WTFString.h>
     52#if defined Q_OS_UNIX
     53#include <sys/prctl.h>
     54#include <signal.h>
     55#endif
    5356
    5457using namespace WebCore;
    5558
    5659namespace WebKit {
    57 
    58 class ProcessLauncherHelper : public QObject {
    59     Q_OBJECT
    60 public:
    61     ~ProcessLauncherHelper();
    62     void launch(WebKit::ProcessLauncher*);
    63     QLocalSocket* takePendingConnection();
    64     static ProcessLauncherHelper* instance();
    65 
    66     const QString serverName() const { return m_server.serverName(); }
    67 
    68 private:
    69     ProcessLauncherHelper();
    70     QLocalServer m_server;
    71     QList<WorkItem*> m_items;
    72 
    73     Q_SLOT void newConnection();
    74 };
    75 
    76 Q_GLOBAL_STATIC(WTF::HashSet<QProcess*>, processes);
    77 
    78 static void cleanupAtExit()
    79 {
    80     // Terminate our web process(es).
    81     WTF::HashSet<QProcess*>::const_iterator end = processes()->end();
    82     for (WTF::HashSet<QProcess*>::const_iterator it = processes()->begin(); it != end; ++it) {
    83         QProcess* process = *it;
    84         process->disconnect(process);
    85         process->terminate();
    86         if (!process->waitForFinished(200))
    87             process->kill();
    88     }
    89 
    90     // Do not leave the socket file behind.
    91     QLocalServer::removeServer(ProcessLauncherHelper::instance()->serverName());
    92 }
    9360
    9461class QtWebProcess : public QProcess
     
    9966        : QProcess(parent)
    10067    {
    101         static bool isRegistered = false;
    102         if (!isRegistered) {
    103             qRegisterMetaType<QProcess::ProcessState>("QProcess::ProcessState");
    104             isRegistered = true;
    105         }
    106 
    107         connect(this, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(processStateChanged(QProcess::ProcessState)));
    10868    }
    10969
    110 private slots:
    111     void processStateChanged(QProcess::ProcessState state);
     70protected:
     71    virtual void setupChildProcess();
    11272};
    11373
    114 void QtWebProcess::processStateChanged(QProcess::ProcessState state)
     74void QtWebProcess::setupChildProcess()
    11575{
    116     QProcess* process = qobject_cast<QProcess*>(sender());
    117     if (!process)
    118         return;
    119 
    120     if (state == QProcess::Running)
    121         processes()->add(process);
    122     else if (state == QProcess::NotRunning)
    123         processes()->remove(process);
     76#if defined Q_OS_UNIX
     77    prctl(PR_SET_PDEATHSIG, SIGKILL);
     78#endif
    12479}
    12580
    126 void ProcessLauncherHelper::launch(WebKit::ProcessLauncher* launcher)
     81void ProcessLauncher::launchProcess()
    12782{
    12883    QString applicationPath = "%1 %2";
     
    13489    }
    13590
    136     QString program(applicationPath.arg(m_server.serverName()));
     91    int sockets[2];
     92    if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
     93        qDebug() << "Creation of socket failed with errno:" << errno;
     94        ASSERT_NOT_REACHED();
     95        return;
     96    }
     97
     98    // Don't expose the ui socket to the web process
     99    while (fcntl(sockets[1], F_SETFD, FD_CLOEXEC == -1)) {
     100        if (errno != EINTR) {
     101            ASSERT_NOT_REACHED();
     102            while (close(sockets[0]) == -1 && errno == EINTR) { }
     103            while (close(sockets[1]) == -1 && errno == EINTR) { }
     104            return;
     105        }
     106    }
     107
     108    QString program(applicationPath.arg(sockets[0]));
    137109
    138110    QProcess* webProcess = new QtWebProcess();
    139111    webProcess->setProcessChannelMode(QProcess::ForwardedChannels);
    140112    webProcess->start(program);
     113
     114    // Don't expose the web socket to possible future web processes
     115    while (fcntl(sockets[0], F_SETFD, FD_CLOEXEC) == -1) {
     116        if (errno != EINTR) {
     117            ASSERT_NOT_REACHED();
     118            delete webProcess;
     119            return;
     120        }
     121    }
    141122
    142123    if (!webProcess->waitForStarted()) {
     
    149130    setpriority(PRIO_PROCESS, webProcess->pid(), 10);
    150131
    151     m_items.append(WorkItem::create(launcher, &WebKit::ProcessLauncher::didFinishLaunchingProcess, webProcess, m_server.serverName()).leakPtr());
    152 }
    153 
    154 QLocalSocket* ProcessLauncherHelper::takePendingConnection()
    155 {
    156     return m_server.nextPendingConnection();
    157 }
    158 
    159 ProcessLauncherHelper::~ProcessLauncherHelper()
    160 {
    161     m_server.close();
    162 }
    163 
    164 ProcessLauncherHelper::ProcessLauncherHelper()
    165 {
    166     srandom(time(0));
    167     if (!m_server.listen("QtWebKit" + QString::number(random()))) {
    168         qDebug() << "Failed to create server socket.";
    169         ASSERT_NOT_REACHED();
    170     }
    171     connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
    172 }
    173 
    174 ProcessLauncherHelper* ProcessLauncherHelper::instance()
    175 {
    176     static ProcessLauncherHelper* result = 0;
    177     if (!result) {
    178         result = new ProcessLauncherHelper();
    179 
    180         // The purpose of the following line is to ensure that our static is initialized before the exit handler is installed.
    181         processes()->clear();
    182 
    183         atexit(cleanupAtExit);
    184     }
    185     return result;
    186 }
    187 
    188 void ProcessLauncherHelper::newConnection()
    189 {
    190     ASSERT(!m_items.isEmpty());
    191 
    192     m_items[0]->execute();
    193     delete m_items[0];
    194     m_items.pop_front();
    195 }
    196 
    197 void ProcessLauncher::launchProcess()
    198 {
    199     ProcessLauncherHelper::instance()->launch(this);
     132    RunLoop::main()->scheduleWork(WorkItem::create(this, &WebKit::ProcessLauncher::didFinishLaunchingProcess, webProcess, sockets[1]));
    200133}
    201134
     
    209142}
    210143
    211 QLocalSocket* ProcessLauncher::takePendingConnection()
    212 {
    213     return ProcessLauncherHelper::instance()->takePendingConnection();
    214 }
    215 
    216144void ProcessLauncher::platformInvalidate()
    217145{
    218     notImplemented();
     146
    219147}
    220148
  • trunk/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp

    r67433 r76507  
    5555    // FIXME: We do not support threaded mode for now.
    5656
    57     WebProcess::shared().initialize("foo", RunLoop::current());
     57    WebProcess::shared().initialize(-1, RunLoop::current());
    5858    RunLoop::run();
    5959
     
    7171    }
    7272
    73     QString serverIdentifier = QString::number(connectionIdentifier);
    74     return serverIdentifier;
     73    return connectionIdentifier;
    7574}
    7675
  • trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp

    r75452 r76507  
    345345#if PLATFORM(MAC)
    346346    m_connection->setShouldCloseConnectionOnMachExceptions();
     347#elif PLATFORM(QT)
     348    m_connection->setShouldCloseConnectionOnProcessTermination(processIdentifier());
    347349#endif
    348    
     350
    349351    m_connection->open();
    350352   
  • trunk/Source/WebKit2/UIProcess/qt/WebContextQt.cpp

    r73221 r76507  
    2929#include "ApplicationCacheStorage.h"
    3030#include "WebProcessCreationParameters.h"
     31#include <QProcess>
    3132
    3233namespace WebKit {
     
    4344void WebContext::platformInitializeWebProcess(WebProcessCreationParameters&)
    4445{
     46    qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
    4547}
    4648
  • trunk/Source/WebKit2/WebKit2.pro

    r76496 r76507  
    233233    Platform/WorkItem.h \
    234234    Platform/WorkQueue.h \
    235     Platform/qt/MappedMemoryPool.h \
    236235    Shared/API/c/WKBase.h \
    237236    Shared/API/c/WKCertificateInfo.h \
     
    294293    Shared/WebUserContentURLPattern.h \
    295294    Shared/Plugins/Netscape/NetscapePluginModule.h \
    296     Shared/qt/CleanupHandler.h \
    297295    Shared/qt/PlatformCertificateInfo.h \
    298296    Shared/qt/UpdateChunk.h \
     
    460458    Platform/CoreIPC/Connection.cpp \
    461459    Platform/CoreIPC/DataReference.cpp \
     460    Platform/CoreIPC/qt/AttachmentQt.cpp \
    462461    Platform/CoreIPC/qt/ConnectionQt.cpp \
    463462    Platform/Logging.cpp \
     
    465464    Platform/RunLoop.cpp \
    466465    Platform/WorkQueue.cpp \
    467     Platform/qt/MappedMemoryPool.cpp \
    468466    Platform/qt/ModuleQt.cpp \
    469467    Platform/qt/RunLoopQt.cpp \
     
    518516    Shared/WebWheelEvent.cpp \
    519517    Shared/qt/ShareableBitmapQt.cpp \
    520     Shared/qt/CleanupHandler.cpp \
    521518    Shared/qt/NativeWebKeyboardEventQt.cpp \
    522519    Shared/qt/UpdateChunk.cpp \
  • trunk/Source/WebKit2/WebProcess/qt/WebProcessMainQt.cpp

    r75046 r76507  
    161161
    162162    // Create the connection.
    163     QString identifier(app->arguments().size() > 1 ? app->arguments().at(1) : "");
     163    if (app->arguments().size() <= 1) {
     164        qDebug() << "Error: wrong number of arguments.";
     165        return 1;
     166    }
     167
     168    bool wasNumber = false;
     169    int identifier = app->arguments().at(1).toInt(&wasNumber, 10);
     170    if (!wasNumber) {
     171        qDebug() << "Error: connection identifier wrong.";
     172        return 1;
     173    }
     174
    164175    WebKit::WebProcess::shared().initialize(identifier, RunLoop::main());
    165176
Note: See TracChangeset for help on using the changeset viewer.