aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvetlana Abramenkova <sabramenkova@luxoft.com>2019-08-20 12:30:05 +0300
committerSvetlana Abramenkova <sabramenkova@luxoft.com>2019-10-08 20:41:07 +0300
commitb5b1f8797925ffd495603b9417a3c71099a1a55c (patch)
treee3ecbfe0fff32515c29ddfaed59e7d602467d300
parentfbcaea63a02187bcd2a2392bb961be3cbb292152 (diff)
"Graceful shutdown" of the QML Live Benchv5.13.1_QtAS
Handling "Ctrl+C" console events and finish all processes Change-Id: I51e0118c2e5e000a111e92066d9551a71a5a3f21 Task-number: AUTOSUITE-993 Reviewed-by: Nikolay Zamotaev <nzamotaev@luxoft.com>
-rw-r--r--src/bench/main.cpp28
-rw-r--r--src/bench/mainwindow.cpp5
-rw-r--r--src/bench/mainwindow.h1
-rw-r--r--src/bench/runtimemanager.cpp33
-rw-r--r--src/bench/runtimemanager.h3
-rw-r--r--src/bench/runtimeprocess.cpp5
-rw-r--r--src/bench/runtimeprocess.h2
-rw-r--r--src/ipc/ipcclient.cpp9
-rw-r--r--src/ipc/ipcclient.h1
-rw-r--r--src/ipc/ipcconnection.cpp6
-rw-r--r--src/ipc/ipcconnection.h1
11 files changed, 85 insertions, 9 deletions
diff --git a/src/bench/main.cpp b/src/bench/main.cpp
index 8f54f9c..ddc0657 100644
--- a/src/bench/main.cpp
+++ b/src/bench/main.cpp
@@ -43,6 +43,8 @@
#include "qmllive_version.h"
#include "projectmanager.h"
+#include <signal.h>
+
class Application : public QApplication
{
Q_OBJECT
@@ -97,6 +99,23 @@ private:
Options *Application::s_options = 0;
+void catchExitSignals(const std::vector<int>& quitSignals,
+ const std::vector<int>& ignoreSignals = std::vector<int>()) {
+
+ auto handler = [](int sig) ->void {
+ qInfo("\nQuit the application (user request signal = %d).\n", sig);
+ Application::quit();
+ };
+
+ // all these signals will be ignored.
+ for ( int sig : ignoreSignals )
+ signal(sig, SIG_IGN);
+
+ // each of these signals calls the handler (quits the QCoreApplication).
+ for ( int sig : quitSignals )
+ signal(sig, handler);
+}
+
Application *Application::create(int &argc, char **argv)
{
setApplicationName("QML Live Bench");
@@ -594,6 +613,15 @@ void SlaveApplication::forwardArguments()
int main(int argc, char** argv)
{
QScopedPointer<Application> app(Application::create(argc, argv));
+
+#if defined (Q_OS_UNIX) || defined (Q_OS_MACOS)
+ catchExitSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP, SIGABRT}); // Linux + Mac
+#endif
+
+#ifdef Q_OS_WIN
+ catchExitSignals({SIGINT, SIGTERM, SIGABRT}); // Windows
+#endif
+
return app->exec();
}
diff --git a/src/bench/mainwindow.cpp b/src/bench/mainwindow.cpp
index d8ffb5e..dc6c964 100644
--- a/src/bench/mainwindow.cpp
+++ b/src/bench/mainwindow.cpp
@@ -109,6 +109,7 @@ MainWindow::MainWindow(QWidget *parent)
, m_projectManager(new ProjectManager(this))
, m_imports (nullptr)
, m_runtimeManager(new RuntimeManager(this))
+ , m_closeEvent(false)
{
setupContent();
setupMenuBar();
@@ -150,6 +151,8 @@ MainWindow::MainWindow(QWidget *parent)
MainWindow::~MainWindow()
{
+ if (!m_closeEvent)
+ writeSettings();
m_runtimeManager->finishProcesses();
delete m_runtimeManager;
}
@@ -400,6 +403,7 @@ void MainWindow::init()
void MainWindow::writeSettings()
{
+ qInfo() << "Writing QML Live Bench user settings...";
QSettings s;
s.setValue("geometry", saveGeometry());
s.setValue("windowState", saveState());
@@ -529,6 +533,7 @@ void MainWindow::setProject(const QString &projectFile)
void MainWindow::closeEvent(QCloseEvent *event)
{
+ m_closeEvent = true;
writeSettings();
m_runtimeManager->finishProcesses();
QMainWindow::closeEvent(event);
diff --git a/src/bench/mainwindow.h b/src/bench/mainwindow.h
index 9360306..382c6a6 100644
--- a/src/bench/mainwindow.h
+++ b/src/bench/mainwindow.h
@@ -143,4 +143,5 @@ private:
ProjectManager *m_projectManager;
QSet<QString> *m_imports;
RuntimeManager *m_runtimeManager;
+ bool m_closeEvent;
};
diff --git a/src/bench/runtimemanager.cpp b/src/bench/runtimemanager.cpp
index 4049819..e45f5c5 100644
--- a/src/bench/runtimemanager.cpp
+++ b/src/bench/runtimemanager.cpp
@@ -41,6 +41,8 @@ RuntimeManager::RuntimeManager(QObject *parent) : QObject(parent)
,m_currentFile(nullptr)
,m_imports(nullptr)
,m_pluginPath(nullptr)
+ ,m_primeRuntimeConnected(false)
+ ,m_primeCurrentFile(nullptr)
{
m_primeRuntime = new RuntimeProcess(this, Constants::PRIMERUNTIME_PORT(), true);
QSettings s;
@@ -53,7 +55,6 @@ RuntimeManager::RuntimeManager(QObject *parent) : QObject(parent)
}
connect(m_primeRuntime, &RuntimeProcess::errorOccurred, this, &RuntimeManager::onPrimeRuntimeError);
connect(m_primeRuntime, &RuntimeProcess::stateChanged, this, &RuntimeManager::onPrimeRuntimeChanged);
- connect(m_primeRuntime, &RuntimeProcess::errorOccurred, this, &RuntimeManager::onError);
}
RuntimeManager::~RuntimeManager()
{
@@ -68,6 +69,7 @@ void RuntimeManager::startPrimeRuntime()
connect(m_primeRuntime, &RuntimeProcess::remoteLog, view, &LogView::appendToLog);
connect(m_primeRuntime, &RuntimeProcess::clearLog, view, &LogView::clear);
connect(m_primeRuntime, &RuntimeProcess::connected, view, &LogView::clear);
+ connect(m_primeRuntime, &RuntimeProcess::connected, this, &RuntimeManager::onPrimeRuntimeConnected);
dock->setWidget(view);
emit logWidgetAdded(dock);
@@ -93,7 +95,11 @@ void RuntimeManager::setLiveHubEngine(LiveHubEngine *engine)
void RuntimeManager::onPrimeRuntimeError(QProcess::ProcessError error)
{
- qWarning()<<"RuntimeManager::onPrimeRuntimeError: "<<error;
+ if (error == QProcess::ProcessError::Crashed) {
+ qWarning() << "QML Live Prime Runtime crashed with QProcess::ExitStatus = " << m_primeRuntime->exitStatus();
+ } else {
+ qWarning() << "RuntimeManager::onPrimeRuntimeError: " << error;
+ }
}
void RuntimeManager::setWorkspace(const QString &workspace)
@@ -144,7 +150,6 @@ void RuntimeManager::setPrimeCurrentFile(const LiveDocument &currentFile)
m_primeRuntime->setLiveHubEngine(m_engine);
m_primeRuntime->start(m_runtimeBinaryPath, arguments);
}
-
m_primeRuntime->setCurrentFile(currentFile);
}
@@ -209,18 +214,22 @@ void RuntimeManager::onRuntimeStarted()
void RuntimeManager::finishProcesses()
{
- qInfo() << "RuntimeManager::finishProcesses ---------KILL ALL CHILD PROCESSES__________";
+ qInfo() << "RuntimeManager::finishProcesses ---------TERMINATE ALL CHILD PROCESSES__________";
for (int i = 0; i < m_runtimes.count(); i++) {
- m_runtimes.at(i)->terminate();
- if (!m_runtimes.at(i)->waitForFinished(500)) {
- m_runtimes.at(i)->kill();
+ if (m_runtimes.at(i)->state() != QProcess::NotRunning) {
+ m_runtimes.at(i)->terminate();
+ if (!m_runtimes.at(i)->waitForFinished(500)) {
+ qInfo() << "QML Live Runtime with port " + QString::number(m_runtimes.at(i)->port()) + " was not finished within 500 msec, KILLING...";
+ m_runtimes.at(i)->kill();
+ }
}
}
if (m_primeRuntime->state() == QProcess::Running || m_primeRuntime->state() == QProcess::Starting){
m_primeRuntime->terminate();
- if (!m_primeRuntime->waitForFinished(100)) {
+ if (!m_primeRuntime->waitForFinished(1000)) {
+ qInfo() << "QML Live Prime Runtime with port " + QString::number(m_primeRuntime->port()) + " was not finished within 500 msec, KILLING...";
m_primeRuntime->kill();
}
}
@@ -327,3 +336,11 @@ void RuntimeManager::stopPrimeRuntime()
m_primeRuntime->clearLog();
m_primeRuntime->remoteLog(LogView::InternalMsgType::InternalInfo, "Please select file for preview.");
}
+
+void RuntimeManager::onPrimeRuntimeConnected()
+{
+ qInfo() << "PrimeRuntime connected ";
+ m_primeRuntimeConnected = true;
+ if (m_primeCurrentFile != nullptr)
+ m_primeRuntime->setCurrentFile(*m_primeCurrentFile);
+}
diff --git a/src/bench/runtimemanager.h b/src/bench/runtimemanager.h
index f4fffe5..fe04f30 100644
--- a/src/bench/runtimemanager.h
+++ b/src/bench/runtimemanager.h
@@ -67,6 +67,7 @@ signals:
public slots:
void onPrimeRuntimeError(QProcess::ProcessError error);
void onPrimeRuntimeChanged();
+ void onPrimeRuntimeConnected();
void setPrimeCurrentFile(const LiveDocument &currentFile);
void newRuntimeWindow(const QString &document);
void initConnectToServer();
@@ -87,6 +88,8 @@ private:
QString* m_pluginPath;
QList<QDockWidget*> m_logDocks;
QList<RuntimeProcess*> m_runtimes;
+ bool m_primeRuntimeConnected;
+ LiveDocument* m_primeCurrentFile;
};
#endif // RUNTIMEMANAGER_H
diff --git a/src/bench/runtimeprocess.cpp b/src/bench/runtimeprocess.cpp
index d3c61b5..2f61d99 100644
--- a/src/bench/runtimeprocess.cpp
+++ b/src/bench/runtimeprocess.cpp
@@ -167,6 +167,11 @@ void RuntimeProcess::updateOutput()
emit remoteLog(QtInfoMsg, log.data());
}
+int RuntimeProcess::port() const
+{
+ return m_port;
+}
+
void RuntimeProcess::onStateChanged()
{
switch (state()) {
diff --git a/src/bench/runtimeprocess.h b/src/bench/runtimeprocess.h
index 24dac96..f5522ce 100644
--- a/src/bench/runtimeprocess.h
+++ b/src/bench/runtimeprocess.h
@@ -48,6 +48,7 @@ public:
void setLiveHubEngine(LiveHubEngine *engine);
void connectToServer();
void connectToServer(int msecs);
+ int port() const;
Q_SIGNALS:
void connected();
@@ -66,7 +67,6 @@ private:
bool m_ismaster;
bool m_doNotConnect;
int m_port;
- int m_waitToConnect;
RemotePublisher m_publisher;
QPointer<LiveHubEngine> m_engine;
LiveDocument *m_document;
diff --git a/src/ipc/ipcclient.cpp b/src/ipc/ipcclient.cpp
index 6fc58e3..eabb06a 100644
--- a/src/ipc/ipcclient.cpp
+++ b/src/ipc/ipcclient.cpp
@@ -110,6 +110,15 @@ IpcClient::IpcClient(QTcpSocket *socket, QObject *parent)
connect(m_socket, &QAbstractSocket::bytesWritten, this, &IpcClient::onBytesWritten);
}
+IpcClient::~IpcClient()
+{
+ DEBUG << "IpcClient::~IpcClient()";
+ if (m_socket != nullptr) {
+ if (m_socket->state() == QAbstractSocket::ConnectedState)
+ m_socket->close();
+ }
+}
+
/*!
* Returns the socket state
*/
diff --git a/src/ipc/ipcclient.h b/src/ipc/ipcclient.h
index 7ab3d1f..09d4df3 100644
--- a/src/ipc/ipcclient.h
+++ b/src/ipc/ipcclient.h
@@ -44,6 +44,7 @@ class IpcClient : public QObject
public:
explicit IpcClient(QObject *parent = 0);
IpcClient(QTcpSocket* socket, QObject *parent = 0);
+ ~IpcClient();
QAbstractSocket::SocketState state() const;
diff --git a/src/ipc/ipcconnection.cpp b/src/ipc/ipcconnection.cpp
index 81ce41e..3ab4b03 100644
--- a/src/ipc/ipcconnection.cpp
+++ b/src/ipc/ipcconnection.cpp
@@ -61,6 +61,12 @@ IpcConnection::IpcConnection(QTcpSocket *socket, QObject *parent)
connect(m_socket, &QAbstractSocket::readyRead, this, &IpcConnection::readData);
}
+IpcConnection::~IpcConnection()
+{
+ DEBUG << "IpcConnection::~IpcConnection() ";
+ if (m_socket != nullptr)
+ close();
+}
/**
* \brief Close the connection and delete it
*/
diff --git a/src/ipc/ipcconnection.h b/src/ipc/ipcconnection.h
index 325c637..7390b64 100644
--- a/src/ipc/ipcconnection.h
+++ b/src/ipc/ipcconnection.h
@@ -40,6 +40,7 @@ class IpcConnection : public QObject
Q_OBJECT
public:
explicit IpcConnection(QTcpSocket* socket, QObject *parent = 0);
+ ~IpcConnection();
QTcpSocket* socket() const;
private:
void setMaxContentSize(qint64 size);