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
+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.
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
};
#include "Connection.h"
#include "ArgumentEncoder.h"
+#include "ProcessLauncher.h"
#include "WebPageProxyMessageKinds.h"
#include "WorkItem.h"
#include <QApplication>
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;
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()) {
}
}
-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)
#ifndef PlatformProcessIdentifier_h
#define PlatformProcessIdentifier_h
+#if PLATFORM(QT)
+class QProcess;
+#endif
+
namespace WebKit {
#if PLATFORM(MAC)
#elif PLATFORM(WIN)
typedef HANDLE PlatformProcessIdentifier;
#elif PLATFORM(QT)
-typedef pid_t PlatformProcessIdentifier;
+typedef QProcess* PlatformProcessIdentifier;
#endif
} // namespace WebKit
#include <wtf/RefPtr.h>
#include <wtf/Threading.h>
+#if PLATFORM(QT)
+ class QLocalSocket;
+#endif
+
namespace WebKit {
class ProcessLauncher : public ThreadSafeShared<ProcessLauncher> {
static CoreIPC::Connection::Identifier createWebThread();
+#if PLATFORM(QT)
+ friend class ProcessLauncherHelper;
+ static QLocalSocket* takePendingConnection();
+#endif
+
private:
explicit ProcessLauncher(Client*);
#include <meegotouch/MComponentData>
#endif
-#ifdef Q_OS_UNIX
-#include <signal.h>
-#endif
-
#include <QApplication>
#include <QDebug>
+#include <QLocalServer>
#include <QProcess>
#include <QtCore/qglobal.h>
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()
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 */)
return 0;
}
+
+#include "WebProcessLauncherQt.moc"