diff options
author | Svetlana Abramenkova <sabramenkova@luxoft.com> | 2019-08-20 12:30:05 +0300 |
---|---|---|
committer | Svetlana Abramenkova <sabramenkova@luxoft.com> | 2019-10-08 20:41:07 +0300 |
commit | b5b1f8797925ffd495603b9417a3c71099a1a55c (patch) | |
tree | e3ecbfe0fff32515c29ddfaed59e7d602467d300 | |
parent | fbcaea63a02187bcd2a2392bb961be3cbb292152 (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.cpp | 28 | ||||
-rw-r--r-- | src/bench/mainwindow.cpp | 5 | ||||
-rw-r--r-- | src/bench/mainwindow.h | 1 | ||||
-rw-r--r-- | src/bench/runtimemanager.cpp | 33 | ||||
-rw-r--r-- | src/bench/runtimemanager.h | 3 | ||||
-rw-r--r-- | src/bench/runtimeprocess.cpp | 5 | ||||
-rw-r--r-- | src/bench/runtimeprocess.h | 2 | ||||
-rw-r--r-- | src/ipc/ipcclient.cpp | 9 | ||||
-rw-r--r-- | src/ipc/ipcclient.h | 1 | ||||
-rw-r--r-- | src/ipc/ipcconnection.cpp | 6 | ||||
-rw-r--r-- | src/ipc/ipcconnection.h | 1 |
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 ¤tFile) 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 ¤tFile); 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); |