mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 08:10:15 +02:00
send quit event during shutdown on thread, with timeout
This commit is contained in:
parent
f5d732f332
commit
40dfcb1e6e
5 changed files with 64 additions and 33 deletions
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <gl/Config.h>
|
#include <gl/Config.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtx/component_wise.hpp>
|
#include <glm/gtx/component_wise.hpp>
|
||||||
|
@ -1570,9 +1572,13 @@ void Application::aboutToQuit() {
|
||||||
|
|
||||||
getActiveDisplayPlugin()->deactivate();
|
getActiveDisplayPlugin()->deactivate();
|
||||||
|
|
||||||
// use the ClosureEventSender via an std::thread (to not use QThread while the application is going down)
|
// use the ClosureEventSender via a QThread to send an event that says the user asked for the app to close
|
||||||
// to send an event that says the user asked for the app to close
|
auto closureEventSender = DependencyManager::get<ClosureEventSender>();
|
||||||
_userQuitThread = std::thread { &ClosureEventSender::sendQuitStart, DependencyManager::get<ClosureEventSender>() };
|
QThread* closureEventThread = new QThread(this);
|
||||||
|
closureEventSender->moveToThread(closureEventThread);
|
||||||
|
// sendQuitEventAsync will bail immediately if the UserActivityLogger is not enabled
|
||||||
|
connect(closureEventThread, &QThread::started, closureEventSender.data(), &ClosureEventSender::sendQuitEventAsync);
|
||||||
|
closureEventThread->start();
|
||||||
|
|
||||||
// Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown.
|
// Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown.
|
||||||
DependencyManager::get<OffscreenUi>()->hide("RunningScripts");
|
DependencyManager::get<OffscreenUi>()->hide("RunningScripts");
|
||||||
|
@ -1738,6 +1744,15 @@ Application::~Application() {
|
||||||
|
|
||||||
_window->deleteLater();
|
_window->deleteLater();
|
||||||
|
|
||||||
|
// make sure that the quit event has finished sending before we take the application down
|
||||||
|
auto closureEventSender = DependencyManager::get<ClosureEventSender>();
|
||||||
|
while (!closureEventSender->hasFinishedQuitEvent() && !closureEventSender->hasTimedOutQuitEvent()) {
|
||||||
|
// yield so we're not spinning
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
// quit the thread used by the closure event sender
|
||||||
|
closureEventSender->thread()->quit();
|
||||||
|
|
||||||
// Can't log to file passed this point, FileLogger about to be deleted
|
// Can't log to file passed this point, FileLogger about to be deleted
|
||||||
qInstallMessageHandler(LogHandler::verboseMessageHandler);
|
qInstallMessageHandler(LogHandler::verboseMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#define hifi_Application_h
|
#define hifi_Application_h
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include <QtCore/QHash>
|
#include <QtCore/QHash>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
|
@ -681,8 +680,6 @@ private:
|
||||||
FileScriptingInterface* _fileDownload;
|
FileScriptingInterface* _fileDownload;
|
||||||
AudioInjector* _snapshotSoundInjector { nullptr };
|
AudioInjector* _snapshotSoundInjector { nullptr };
|
||||||
SharedSoundPointer _snapshotSound;
|
SharedSoundPointer _snapshotSound;
|
||||||
|
|
||||||
std::thread _userQuitThread;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,11 @@
|
||||||
#include <SandboxUtils.h>
|
#include <SandboxUtils.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
|
||||||
#include "AddressManager.h"
|
#include "AddressManager.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "UserActivityLogger.h"
|
#include "UserActivityLogger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "networking/ClosureEventSender.h"
|
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
#ifdef HAS_BUGSPLAT
|
||||||
#include <BugSplat.h>
|
#include <BugSplat.h>
|
||||||
|
@ -268,12 +266,6 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
Application::shutdownPlugins();
|
Application::shutdownPlugins();
|
||||||
|
|
||||||
if (UserActivityLogger::getInstance().isEnabled()) {
|
|
||||||
// send a quit finished event here to indicate that this session closed cleanly
|
|
||||||
std::thread quitCompleteThread { &::ClosureEventSender::sendQuitFinish, DependencyManager::get<ClosureEventSender>() };
|
|
||||||
quitCompleteThread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(interfaceapp, "Normal exit.");
|
qCDebug(interfaceapp, "Normal exit.");
|
||||||
#if !defined(DEBUG) && !defined(Q_OS_LINUX)
|
#if !defined(DEBUG) && !defined(Q_OS_LINUX)
|
||||||
// HACK: exit immediately (don't handle shutdown callbacks) for Release build
|
// HACK: exit immediately (don't handle shutdown callbacks) for Release build
|
||||||
|
|
|
@ -9,14 +9,15 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QtCore/QDateTime>
|
||||||
#include <QtCore/QEventLoop>
|
#include <QtCore/QEventLoop>
|
||||||
#include <QtCore/QJsonDocument>
|
#include <QtCore/QJsonDocument>
|
||||||
#include <QtNetwork/QHttpMultiPart>
|
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
|
#include <NetworkLogging.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
|
@ -43,11 +44,13 @@ QNetworkRequest createNetworkRequest() {
|
||||||
|
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
|
||||||
|
request.setPriority(QNetworkRequest::HighPriority);
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray postDataForAction(QString action) {
|
QByteArray postDataForAction(QString action) {
|
||||||
return QString("{\"action\": \"" + action + "\"}").toUtf8();
|
return QString("{\"action_name\": \"" + action + "\"}").toUtf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkReply* replyForAction(QString action) {
|
QNetworkReply* replyForAction(QString action) {
|
||||||
|
@ -55,17 +58,33 @@ QNetworkReply* replyForAction(QString action) {
|
||||||
return networkAccessManager.post(createNetworkRequest(), postDataForAction(action));
|
return networkAccessManager.post(createNetworkRequest(), postDataForAction(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClosureEventSender::sendQuitStart() {
|
void ClosureEventSender::sendQuitEventAsync() {
|
||||||
|
if (UserActivityLogger::getInstance().isEnabled()) {
|
||||||
QNetworkReply* reply = replyForAction("quit_start");
|
QNetworkReply* reply = replyForAction("quit");
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &ClosureEventSender::handleQuitEventFinished);
|
||||||
QEventLoop loop;
|
_quitEventStartTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
} else {
|
||||||
|
_hasFinishedQuitEvent = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClosureEventSender::sendQuitFinish() {
|
void ClosureEventSender::handleQuitEventFinished() {
|
||||||
QNetworkReply* reply = replyForAction("quit_finish");
|
_hasFinishedQuitEvent = true;
|
||||||
|
|
||||||
QEventLoop loop;
|
auto reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
qCDebug(networking) << "Quit event sent successfully";
|
||||||
|
} else {
|
||||||
|
qCDebug(networking) << "Failed to send quit event -" << reply->errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClosureEventSender::hasTimedOutQuitEvent() {
|
||||||
|
const int CLOSURE_EVENT_TIMEOUT_MS = 5000;
|
||||||
|
return _quitEventStartTimestamp != 0
|
||||||
|
&& QDateTime::currentMSecsSinceEpoch() - _quitEventStartTimestamp > CLOSURE_EVENT_TIMEOUT_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,24 +12,32 @@
|
||||||
#ifndef hifi_ClosureEventSender_h
|
#ifndef hifi_ClosureEventSender_h
|
||||||
#define hifi_ClosureEventSender_h
|
#define hifi_ClosureEventSender_h
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
class ClosureEventSender : public Dependency {
|
class ClosureEventSender : public QObject, public Dependency {
|
||||||
|
Q_OBJECT
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setSessionID(QUuid sessionID) { _sessionID = sessionID; }
|
void sendCrashEventSync();
|
||||||
|
|
||||||
void sendQuitStart();
|
bool hasTimedOutQuitEvent();
|
||||||
void sendQuitFinish();
|
bool hasFinishedQuitEvent() { return _hasFinishedQuitEvent; }
|
||||||
void sendCrashEvent();
|
|
||||||
|
public slots:
|
||||||
|
void sendQuitEventAsync();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleQuitEventFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUuid _sessionID;
|
std::atomic<bool> _hasFinishedQuitEvent { false };
|
||||||
QString _accessToken;
|
std::atomic<int64_t> _quitEventStartTimestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ClosureEventSender_h
|
#endif // hifi_ClosureEventSender_h
|
||||||
|
|
Loading…
Reference in a new issue