diff options
author | Andrew Christian <andrew.christian@nokia.com> | 2012-02-08 12:52:17 -0500 |
---|---|---|
committer | Chris Craig <ext-chris.craig@nokia.com> | 2012-02-08 22:37:30 +0100 |
commit | 1b55e397a94ad39adaaf21276a74605ea999ab1a (patch) | |
tree | 4bb9a99e801abf88caa7688f09358efdd325726e | |
parent | 458c47468386fa51c20f862561d50dcbd05da15b (diff) |
Updating prelaunch backend factory.
* Factory now restarts a failed prelaunched process.
* Factory has "launchInterval" property to allow changing how
frequently the prelaunched process is started.
Change-Id: I870222b7d4b8a893477c254be72277e0380be5d6
Reviewed-by: Chris Craig <ext-chris.craig@nokia.com>
-rw-r--r-- | src/core/prelaunchprocessbackend.cpp | 20 | ||||
-rw-r--r-- | src/core/prelaunchprocessbackendfactory.cpp | 48 | ||||
-rw-r--r-- | src/core/prelaunchprocessbackendfactory.h | 9 | ||||
-rw-r--r-- | tests/auto/processmanager/tst_processmanager.cpp | 32 |
4 files changed, 92 insertions, 17 deletions
diff --git a/src/core/prelaunchprocessbackend.cpp b/src/core/prelaunchprocessbackend.cpp index 27142f5..f855af4 100644 --- a/src/core/prelaunchprocessbackend.cpp +++ b/src/core/prelaunchprocessbackend.cpp @@ -167,13 +167,12 @@ QProcess::ProcessState PrelaunchProcessBackend::state() const void PrelaunchProcessBackend::handleProcessStarted() { UnixProcessBackend::handleProcessStarted(); - if (m_started) - emit started(); - else { + if (!m_started) { QueuedSignal s; s.name = QueuedSignal::Started; m_queue << s; } + emit started(); } /*! @@ -182,14 +181,13 @@ void PrelaunchProcessBackend::handleProcessStarted() void PrelaunchProcessBackend::handleProcessError(QProcess::ProcessError processError) { UnixProcessBackend::handleProcessError(processError); - if (m_started) - emit error(processError); - else { + if (!m_started) { QueuedSignal s; s.name = QueuedSignal::Error; s.n.error = processError; m_queue << s; } + emit error(processError); } /*! @@ -198,15 +196,14 @@ void PrelaunchProcessBackend::handleProcessError(QProcess::ProcessError processE void PrelaunchProcessBackend::handleProcessFinished(int exitCode, QProcess::ExitStatus status) { UnixProcessBackend::handleProcessFinished(exitCode, status); - if (m_started) - emit finished(exitCode, status); - else { + if (!m_started) { QueuedSignal s; s.name = QueuedSignal::Finished; s.n.f.exitCode = exitCode; s.n.f.exitStatus = status; m_queue << s; } + emit finished(exitCode, status); } /*! @@ -215,14 +212,13 @@ void PrelaunchProcessBackend::handleProcessFinished(int exitCode, QProcess::Exit void PrelaunchProcessBackend::handleProcessStateChanged(QProcess::ProcessState state) { UnixProcessBackend::handleProcessStateChanged(state); - if (m_started) - emit stateChanged(state); - else { + if (!m_started) { QueuedSignal s; s.name = QueuedSignal::StateChanged; s.n.state = state; m_queue << s; } + emit stateChanged(state); } /*! diff --git a/src/core/prelaunchprocessbackendfactory.cpp b/src/core/prelaunchprocessbackendfactory.cpp index ccb5a1f..33a20b5 100644 --- a/src/core/prelaunchprocessbackendfactory.cpp +++ b/src/core/prelaunchprocessbackendfactory.cpp @@ -107,6 +107,7 @@ ProcessBackend * PrelaunchProcessBackendFactory::create(const ProcessInfo& info, m_timer.start(); prelaunch->setInfo(info); prelaunch->setParent(parent); + prelaunch->disconnect(this); } else { // qDebug() << "Creating prelaunch from scratch"; @@ -130,6 +131,31 @@ QList<Q_PID> PrelaunchProcessBackendFactory::internalProcesses() } /*! + Return the current launch interval in milliseconds + */ + +int PrelaunchProcessBackendFactory::launchInterval() const +{ + return m_timer.interval(); +} + +/*! + Set the current launch interval to \a interval milliseconds +*/ + +void PrelaunchProcessBackendFactory::setLaunchInterval(int interval) +{ + if (m_timer.interval() != interval) { + bool active = m_timer.isActive(); + m_timer.stop(); + m_timer.setInterval(interval); + if (active) + m_timer.start(); + emit launchIntervalChanged(); + } +} + +/*! Under memory restriction, terminate the prelaunch process. */ @@ -147,15 +173,37 @@ void PrelaunchProcessBackendFactory::handleMemoryRestrictionChange() } } +/*! + Launch a new prelaunched process backend. + In the future, it would be useful if the launch didn't require a timeout. + */ + void PrelaunchProcessBackendFactory::timeout() { Q_ASSERT(m_prelaunch == NULL); Q_ASSERT(!m_memoryRestricted); m_prelaunch = new PrelaunchProcessBackend(m_info, this); + connect(m_prelaunch, SIGNAL(finished(int,QProcess::ExitStatus)), + SLOT(prelaunchFinished(int,QProcess::ExitStatus))); m_prelaunch->prestart(); } +/*! + Handle a surprise termination condition - the prelaunched process died + unexpectedly. + */ + +void PrelaunchProcessBackendFactory::prelaunchFinished(int exitCode, QProcess::ExitStatus status) +{ + qWarning() << Q_FUNC_INFO << "died unexpectedly" << exitCode << status; + if (m_prelaunch) { + delete m_prelaunch; + m_prelaunch = NULL; + } + m_timer.start(); +} + #include "moc_prelaunchprocessbackendfactory.cpp" QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/prelaunchprocessbackendfactory.h b/src/core/prelaunchprocessbackendfactory.h index 3f1d087..5702b77 100644 --- a/src/core/prelaunchprocessbackendfactory.h +++ b/src/core/prelaunchprocessbackendfactory.h @@ -52,6 +52,8 @@ class PrelaunchProcessBackend; class Q_ADDON_PROCESSMANAGER_EXPORT PrelaunchProcessBackendFactory : public ProcessBackendFactory { Q_OBJECT + Q_PROPERTY(int launchInterval READ launchInterval WRITE setLaunchInterval NOTIFY launchIntervalChanged) + public: PrelaunchProcessBackendFactory(const ProcessInfo& info, QObject *parent = 0); virtual ~PrelaunchProcessBackendFactory(); @@ -60,11 +62,18 @@ public: virtual QList<Q_PID> internalProcesses(); + int launchInterval() const; + void setLaunchInterval(int interval); + +signals: + void launchIntervalChanged(); + protected: virtual void handleMemoryRestrictionChange(); private slots: void timeout(); + void prelaunchFinished(int, QProcess::ExitStatus); private: PrelaunchProcessBackend *m_prelaunch; diff --git a/tests/auto/processmanager/tst_processmanager.cpp b/tests/auto/processmanager/tst_processmanager.cpp index ee9d276..cc35e89 100644 --- a/tests/auto/processmanager/tst_processmanager.cpp +++ b/tests/auto/processmanager/tst_processmanager.cpp @@ -56,6 +56,8 @@ #include "pipeprocessbackendfactory.h" #include "socketprocessbackendfactory.h" +#include <signal.h> + QT_USE_NAMESPACE_PROCESSMANAGER Q_DECLARE_METATYPE(QProcess::ExitStatus); @@ -138,7 +140,7 @@ bool isProcessStopped(Q_PID pid) return false; } -static void waitForInternalProcess(ProcessBackendManager *manager, int timeout=5000) +static void waitForInternalProcess(ProcessBackendManager *manager, int num=1, int timeout=5000) { QTime stopWatch; stopWatch.start(); @@ -146,7 +148,7 @@ static void waitForInternalProcess(ProcessBackendManager *manager, int timeout=5 QTestEventLoop::instance().enterLoop(1); if (stopWatch.elapsed() >= timeout) QFAIL("Timed out"); - if (manager->internalProcesses().count() == 1) + if (manager->internalProcesses().count() == num) break; } } @@ -713,6 +715,8 @@ private slots: void socketLauncherOomChangeAfter() { socketLauncherTest(oomChangeAfterClient); } #endif + void prelaunchChildAbort(); + void frontend(); void subclassFrontend(); }; @@ -999,11 +1003,30 @@ void tst_ProcessManager::socketLauncherCrash() delete remote; } - */ +*/ + +void tst_ProcessManager::prelaunchChildAbort() +{ + ProcessBackendManager *manager = new ProcessBackendManager; + ProcessInfo info; + info.setValue("program", "testPrelaunch/testPrelaunch"); + PrelaunchProcessBackendFactory *factory = new PrelaunchProcessBackendFactory(info); + manager->addFactory(factory); + + // The factory should not have launched + QVERIFY(manager->internalProcesses().count() == 0); + + waitForInternalProcess(manager, 1, factory->launchInterval() + 2000); + Q_PID pid = manager->internalProcesses().at(0); + // Kill the prelaunched process and verify that it is restarted + ::kill(pid, SIGKILL); + waitForInternalProcess(manager, 0); + waitForInternalProcess(manager, 1, factory->launchInterval() + 2000); + delete manager; +} void tst_ProcessManager::frontend() { - QString socketname = "/tmp/tst_socket"; ProcessManager *manager = new ProcessManager; manager->addBackendFactory(new StandardProcessBackendFactory); @@ -1061,7 +1084,6 @@ private: void tst_ProcessManager::subclassFrontend() { - QString socketname = "/tmp/tst_socket"; TestManager *manager = new TestManager; manager->addBackendFactory(new StandardProcessBackendFactory); |