2010-07-08 Luiz Agostini <luiz@webkit.org>, Kenneth Rohde Christiansen <kenneth...
authorkenneth@webkit.org <kenneth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Jul 2010 16:01:42 +0000 (16:01 +0000)
committerkenneth@webkit.org <kenneth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Jul 2010 16:01:42 +0000 (16:01 +0000)
        Reviewed by Antti Koivisto.

        [Qt] Improve QtWebkit2 secondary process launching procedure
        https://bugs.webkit.org/show_bug.cgi?id=41853

        Changing secondary process launching procedure to make sure that the method
        ProcessLauncher::didFinishLaunchingProcess will only be called after secondary
        process has been launched and the connection has been stablished between the
        UIProcess and WebProcess.

        This solves the timing issues ocasionaly observed when launching MiniBrowser.

        QLocalServer object and related code has been removed from the class Connection.
        Server instances of the Connection class now get the QLocalSocket via ProcessLauncher.

        * Platform/CoreIPC/Connection.h:
        * Platform/CoreIPC/qt/ConnectionQt.cpp:
        (CoreIPC::Connection::platformInitialize):
        (CoreIPC::Connection::platformInvalidate):
        (CoreIPC::Connection::open):

        Using QProcess* as PlatformProcessIdentifier.

        * Platform/PlatformProcessIdentifier.h:

        A new singleton class named ProcessLauncherHelper was created to handle the QLocalServer
        object used to receive connections. This class launches the process and waits for it to connect
        before calling ProcessLauncher::didFinishLaunchingProcess.

        * UIProcess/Launcher/ProcessLauncher.h:
        * UIProcess/Launcher/qt/ProcessLauncherQt.cpp:
        (WebKit::ProcessLauncherHelper::launch):
        (WebKit::ProcessLauncherHelper::takePendingConnection):
        (WebKit::ProcessLauncherHelper::ProcessLauncherHelper):
        (WebKit::ProcessLauncherHelper::instance):
        (WebKit::ProcessLauncherHelper::newConnection):
        (WebKit::ProcessLauncher::launchProcess):
        (WebKit::ProcessLauncher::terminateProcess):
        (_qt_takePendingConnection):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@62790 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit2/ChangeLog
WebKit2/Platform/CoreIPC/Connection.h
WebKit2/Platform/CoreIPC/qt/ConnectionQt.cpp
WebKit2/Platform/PlatformProcessIdentifier.h
WebKit2/UIProcess/Launcher/ProcessLauncher.h
WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp

index a95b00c..32bb025 100644 (file)
@@ -1,3 +1,45 @@
+2010-07-08  Luiz Agostini  <luiz@webkit.org>, Kenneth Rohde Christiansen <kenneth@webkit.org>
+
+        Reviewed by Antti Koivisto.
+
+        [Qt] Improve QtWebkit2 secondary process launching procedure
+        https://bugs.webkit.org/show_bug.cgi?id=41853
+
+        Changing secondary process launching procedure to make sure that the method
+        ProcessLauncher::didFinishLaunchingProcess will only be called after secondary
+        process has been launched and the connection has been stablished between the
+        UIProcess and WebProcess.
+
+        This solves the timing issues ocasionaly observed when launching MiniBrowser.
+
+        QLocalServer object and related code has been removed from the class Connection.
+        Server instances of the Connection class now get the QLocalSocket via ProcessLauncher.
+
+        * Platform/CoreIPC/Connection.h:
+        * Platform/CoreIPC/qt/ConnectionQt.cpp:
+        (CoreIPC::Connection::platformInitialize):
+        (CoreIPC::Connection::platformInvalidate):
+        (CoreIPC::Connection::open):
+
+        Using QProcess* as PlatformProcessIdentifier.
+
+        * Platform/PlatformProcessIdentifier.h:
+
+        A new singleton class named ProcessLauncherHelper was created to handle the QLocalServer
+        object used to receive connections. This class launches the process and waits for it to connect
+        before calling ProcessLauncher::didFinishLaunchingProcess.
+
+        * UIProcess/Launcher/ProcessLauncher.h:
+        * UIProcess/Launcher/qt/ProcessLauncherQt.cpp:
+        (WebKit::ProcessLauncherHelper::launch):
+        (WebKit::ProcessLauncherHelper::takePendingConnection):
+        (WebKit::ProcessLauncherHelper::ProcessLauncherHelper):
+        (WebKit::ProcessLauncherHelper::instance):
+        (WebKit::ProcessLauncherHelper::newConnection):
+        (WebKit::ProcessLauncher::launchProcess):
+        (WebKit::ProcessLauncher::terminateProcess):
+        (_qt_takePendingConnection):
+
 2010-07-08  Antti Koivisto  <koivisto@iki.fi>
 
         Reviewed by Kenneth Rohde Christiansen.
index 5827d3d..8d8e0cc 100644 (file)
@@ -173,14 +173,11 @@ private:
     HANDLE m_connectionPipe;
 #elif PLATFORM(QT)
     // Called on the connection queue.
-    void openConnectionHandler();
-    void newConnectionHandler();
     void readyReadHandler();
 
     Vector<uint8_t> m_readBuffer;
     size_t m_currentMessageSize;
     QLocalSocket* m_socket;
-    QLocalServer* m_server;
     QString m_serverName;
 #endif
 };
index 4c83379..f223314 100644 (file)
@@ -27,6 +27,7 @@
 #include "Connection.h"
 
 #include "ArgumentEncoder.h"
+#include "ProcessLauncher.h"
 #include "WebPageProxyMessageKinds.h"
 #include "WorkItem.h"
 #include <QApplication>
@@ -42,8 +43,7 @@ static const size_t messageMaxSize = 4096;
 
 void Connection::platformInitialize(Identifier identifier)
 {
-    m_serverName = "QtWebKit" + identifier;
-    m_server = 0;
+    m_serverName = identifier;
     m_socket = 0;
     m_readBuffer.resize(messageMaxSize);
     m_currentMessageSize = 0;
@@ -51,18 +51,9 @@ void Connection::platformInitialize(Identifier identifier)
 
 void Connection::platformInvalidate()
 {
-    delete m_server;
     delete m_socket;
 }
 
-void Connection::newConnectionHandler()
-{
-    m_socket = m_server->nextPendingConnection();
-    m_isConnected = m_socket;
-    if (m_isConnected)
-        m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
-}
-
 void Connection::readyReadHandler()
 {
     while (m_socket->bytesAvailable()) {
@@ -93,30 +84,22 @@ void Connection::readyReadHandler()
     }
 }
 
-void Connection::openConnectionHandler()
+bool Connection::open()
 {
-    ASSERT(!m_server);
     ASSERT(!m_socket);
 
     if (m_isServer) {
-        m_server = new QLocalServer();
-        if (!m_server->listen(m_serverName)) {
-            qDebug() << "failed to create server " << m_serverName;
-            return;
-        }
-        m_connectionQueue.connectSignal(m_server, SIGNAL(newConnection()), WorkItem::create(this, &Connection::newConnectionHandler));
+        m_socket = WebKit::ProcessLauncher::takePendingConnection();
+        m_isConnected = m_socket;
+        if (m_isConnected)
+            m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
     } else {
         m_socket = new QLocalSocket();
         m_socket->connectToServer(m_serverName);
         m_connectionQueue.connectSignal(m_socket, SIGNAL(readyRead()), WorkItem::create(this, &Connection::readyReadHandler));
         m_isConnected = m_socket->waitForConnected();
     }
-}
-
-bool Connection::open()
-{
-    m_connectionQueue.scheduleWork(WorkItem::create(this, &Connection::openConnectionHandler));
-    return false;
+    return m_isConnected;
 }
 
 void Connection::sendOutgoingMessage(MessageID messageID, auto_ptr<ArgumentEncoder> arguments)
index c38d797..ad1e394 100644 (file)
 #ifndef PlatformProcessIdentifier_h
 #define PlatformProcessIdentifier_h
 
+#if PLATFORM(QT)
+class QProcess;
+#endif
+
 namespace WebKit {
 
 #if PLATFORM(MAC)
@@ -34,7 +38,7 @@ typedef pid_t PlatformProcessIdentifier;
 #elif PLATFORM(WIN)
 typedef HANDLE PlatformProcessIdentifier;
 #elif PLATFORM(QT)
-typedef pid_t PlatformProcessIdentifier;
+typedef QProcess* PlatformProcessIdentifier;
 #endif
 
 } // namespace WebKit 
index e44d63b..6c5e24d 100644 (file)
 #include <wtf/RefPtr.h>
 #include <wtf/Threading.h>
 
+#if PLATFORM(QT)
+    class QLocalSocket;
+#endif
+
 namespace WebKit {
 
 class ProcessLauncher : public ThreadSafeShared<ProcessLauncher> {
@@ -55,6 +59,11 @@ public:
 
     static CoreIPC::Connection::Identifier createWebThread();
 
+#if PLATFORM(QT)
+    friend class ProcessLauncherHelper;
+    static QLocalSocket* takePendingConnection();
+#endif
+
 private:
     explicit ProcessLauncher(Client*);
 
index 23af1f0..4977dce 100644 (file)
 #include <meegotouch/MComponentData>
 #endif
 
-#ifdef Q_OS_UNIX
-#include <signal.h>
-#endif
-
 #include <QApplication>
 #include <QDebug>
+#include <QLocalServer>
 #include <QProcess>
 
 #include <QtCore/qglobal.h>
@@ -64,28 +61,72 @@ using namespace WebCore;
 
 namespace WebKit {
 
-void ProcessLauncher::launchProcess()
+class ProcessLauncherHelper : public QObject {
+    Q_OBJECT
+public:
+    void launch(WebKit::ProcessLauncher*);
+    QLocalSocket* takePendingConnection();
+    static ProcessLauncherHelper* instance();
+private:
+    ProcessLauncherHelper();
+    QLocalServer m_server;
+    QList<WorkItem*> m_items;
+
+    Q_SLOT void newConnection();
+};
+
+void ProcessLauncherHelper::launch(WebKit::ProcessLauncher* launcher)
 {
-    srandom(time(0));
-    QString connectionIdentifier = QString::number(random());
+    QString program("QtWebProcess " + m_server.serverName());
 
-    QString program("QtWebProcess " + connectionIdentifier);
-
-    QProcess* webProcess = new QProcess;
+    QProcess* webProcess = new QProcess();
     webProcess->start(program);
 
     if (!webProcess->waitForStarted()) {
         qDebug() << "Failed to start" << program;
         ASSERT_NOT_REACHED();
+        delete webProcess;
+        return;
+    }
+
+    setpriority(PRIO_PROCESS, webProcess->pid(), 10);
+
+    m_items.append(WorkItem::create(launcher, &WebKit::ProcessLauncher::didFinishLaunchingProcess, webProcess, m_server.serverName()).release());
+}
+
+QLocalSocket* ProcessLauncherHelper::takePendingConnection()
+{
+    return m_server.nextPendingConnection();
+}
+
+ProcessLauncherHelper::ProcessLauncherHelper()
+{
+    srandom(time(0));
+    if (!m_server.listen("QtWebKit" + QString::number(random()))) {
+        qDebug() << "Failed to create server socket.";
+        ASSERT_NOT_REACHED();
     }
+    connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+}
 
-    PlatformProcessIdentifier processIdentifier = webProcess->pid();
-    setpriority(PRIO_PROCESS, processIdentifier, 10);
+ProcessLauncherHelper* ProcessLauncherHelper::instance()
+{
+    static ProcessLauncherHelper* result = new ProcessLauncherHelper();
+    return result;
+}
 
-    qDebug() << program << "nice" << getpriority(PRIO_PROCESS, processIdentifier);
+void ProcessLauncherHelper::newConnection()
+{
+    ASSERT(!m_items.isEmpty());
 
-    // We've finished launching the process, message back to the run loop.
-    RunLoop::main()->scheduleWork(WorkItem::create(this, &ProcessLauncher::didFinishLaunchingProcess, processIdentifier, connectionIdentifier));
+    m_items[0]->execute();
+    delete m_items[0];
+    m_items.pop_front();
+}
+
+void ProcessLauncher::launchProcess()
+{
+    ProcessLauncherHelper::instance()->launch(this);
 }
 
 void ProcessLauncher::terminateProcess()
@@ -93,9 +134,13 @@ void ProcessLauncher::terminateProcess()
     if (!m_processIdentifier)
         return;
 
-#ifdef Q_OS_UNIX
-    kill(m_processIdentifier, SIGKILL);
-#endif
+    QObject::connect(m_processIdentifier, SIGNAL(finished(int)), m_processIdentifier, SLOT(deleteLater()), Qt::QueuedConnection);
+    m_processIdentifier->kill();
+}
+
+QLocalSocket* ProcessLauncher::takePendingConnection()
+{
+    return ProcessLauncherHelper::instance()->takePendingConnection();
 }
 
 static void* webThreadBody(void* /* context */)
@@ -152,3 +197,5 @@ QWEBKIT_EXPORT int webProcessMain(int argc, char** argv)
 
     return 0;
 }
+
+#include "WebProcessLauncherQt.moc"