From a7d2373f3eeb542e4c4995fe66630a97453ccabd Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 19 Apr 2016 16:17:39 -0700 Subject: [PATCH 1/4] Use our ShutdownEventListener utility in Interface, and absorb quit signal when we handle it. --- interface/src/Application.cpp | 7 +++++++ libraries/shared/src/ShutdownEventListener.cpp | 1 + 2 files changed, 8 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e01fe85c3..ded414ceab 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #include @@ -717,6 +718,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us +#ifdef _WIN32 + installNativeEventFilter(&ShutdownEventListener::getInstance()); +#else + ShutdownEventListener::getInstance(); +#endif // Save avatar location immediately after a teleport. connect(getMyAvatar(), &MyAvatar::positionGoneTo, diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index e640126b7b..fa2209f9b7 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -47,6 +47,7 @@ bool ShutdownEventListener::nativeEventFilter(const QByteArray &eventType, void* if (message->message == WM_CLOSE) { // tell our registered application to quit QMetaObject::invokeMethod(qApp, "quit"); + return true; // Don't zombify the application by OS-exitting. Let the application quit in the normal quit-signal way. } } #endif From b22123211776ed6aac994430f40ff7ac7b49b100 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 20 Apr 2016 10:31:26 -0700 Subject: [PATCH 2/4] Windows-only version, without changing assignment-client/domain-server classes. --- interface/src/Application.cpp | 12 ++++++------ libraries/shared/src/ShutdownEventListener.cpp | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ded414ceab..fff65a6955 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -366,6 +366,12 @@ public: return true; } } + + if (message->message == WM_CLOSE) { + // tell our registered application to quit + QMetaObject::invokeMethod(qApp, "quit"); + return true; // Don't zombify the application by OS-exitting. Let the application quit in the normal quit-signal way. + } } return false; } @@ -718,12 +724,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); - // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us -#ifdef _WIN32 - installNativeEventFilter(&ShutdownEventListener::getInstance()); -#else - ShutdownEventListener::getInstance(); -#endif // Save avatar location immediately after a teleport. connect(getMyAvatar(), &MyAvatar::positionGoneTo, diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index fa2209f9b7..e640126b7b 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -47,7 +47,6 @@ bool ShutdownEventListener::nativeEventFilter(const QByteArray &eventType, void* if (message->message == WM_CLOSE) { // tell our registered application to quit QMetaObject::invokeMethod(qApp, "quit"); - return true; // Don't zombify the application by OS-exitting. Let the application quit in the normal quit-signal way. } } #endif From 77d6e0e3e9e02cf8ced35e822e76f6f7a9051ab1 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 20 Apr 2016 10:34:10 -0700 Subject: [PATCH 3/4] Remove include. --- interface/src/Application.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fff65a6955..21cb4c8ec2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -91,7 +91,6 @@ #include #include #include -#include #include #include #include From 0544bcaacd15d83485352ace2e9f5446ed3a948b Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 20 Apr 2016 15:02:41 -0700 Subject: [PATCH 4/4] Simpler cross-platform solution, with comments. --- interface/src/Application.cpp | 6 ------ libraries/ui/src/MainWindow.cpp | 9 +++++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 21cb4c8ec2..4e01fe85c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -365,12 +365,6 @@ public: return true; } } - - if (message->message == WM_CLOSE) { - // tell our registered application to quit - QMetaObject::invokeMethod(qApp, "quit"); - return true; // Don't zombify the application by OS-exitting. Let the application quit in the normal quit-signal way. - } } return false; } diff --git a/libraries/ui/src/MainWindow.cpp b/libraries/ui/src/MainWindow.cpp index ce23bd02a2..bc67a726bd 100644 --- a/libraries/ui/src/MainWindow.cpp +++ b/libraries/ui/src/MainWindow.cpp @@ -64,6 +64,15 @@ void MainWindow::saveGeometry() { } void MainWindow::closeEvent(QCloseEvent* event) { + // It is the job of Application::quit() to shut things down properly when it is finished with its event loop. + // But if we don't explicitly ignore this event now, the window and application event loop will close + // before we've had a chance to act on the aboutToClose signal. This will leaves a zombie process on all platforms. + // To repro: + // Open a QML modal dialog (e.g., select an avatar to wear), but don't dismiss it. + // Close the application with the operating system window close button (not the menu Quit) + // With ignore: App will wait until you accept or dismiss the dialog and log "Normal exit". + // Without ignore: App will close immediately, and nothing will log about quitting or exit. + event->ignore(); qApp->quit(); }