From 4169e9be9d163977a303ef5042c8fcd5be1db9d9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 14:24:31 -0800 Subject: [PATCH 1/3] Don't deadlock objreader on shutdown --- libraries/fbx/src/OBJReader.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 11164afbbb..ff33246b3f 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -260,10 +260,22 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest netRequest(url); QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest); + if (!qApp) { + return netReply; + } QEventLoop loop; // Create an event loop that will quit when we get the finished signal QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); // Nothing is going to happen on this whole run thread until we get this - netReply->waitForReadyRead(-1); // so we might as well block this thread waiting for the response, rather than + + bool aboutToQuit { false }; + auto connection = QObject::connect(qApp, &QCoreApplication::aboutToQuit, [&] { + aboutToQuit = true; + }); + static const int WAIT_TIMEOUT_MS = 500; + while (qApp && !aboutToQuit && !netReply->isReadable()) { + netReply->waitForReadyRead(WAIT_TIMEOUT_MS); // so we might as well block this thread waiting for the response, rather than + } + QObject::disconnect(connection); return netReply; // trying to sync later on. } From b4a7dc113eac8dd6173ab8e8c640554b1e3be90d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 14:25:30 -0800 Subject: [PATCH 2/3] Safer shutdown behavior in QML surfaces --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 13 ++++++++----- libraries/gl/src/gl/OffscreenQmlSurface.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index e22feb694d..6ec162585b 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -315,6 +315,8 @@ OffscreenQmlSurface::OffscreenQmlSurface() { } OffscreenQmlSurface::~OffscreenQmlSurface() { + QObject::disconnect(&_updateTimer); + QObject::disconnect(qApp); _renderer->stop(); delete _rootItem; delete _renderer; @@ -322,6 +324,10 @@ OffscreenQmlSurface::~OffscreenQmlSurface() { delete _qmlEngine; } +void OffscreenQmlSurface::onAboutToQuit() { + QObject::disconnect(&_updateTimer); +} + void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { _renderer = new OffscreenQmlRenderer(this, shareContext); _renderer->_renderControl->_renderWindow = _proxyWindow; @@ -334,12 +340,9 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { // When Quick says there is a need to render, we will not render immediately. Instead, // a timer with a small interval is used to get better performance. _updateTimer.setInterval(MIN_TIMER_MS); - connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); - QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]{ - disconnect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); - }); + QObject::connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); + QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &OffscreenQmlSurface::onAboutToQuit); _updateTimer.start(); - _qmlComponent = new QQmlComponent(_qmlEngine); _qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 5641d16a30..9142e7f2ef 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -74,6 +74,7 @@ signals: public slots: void requestUpdate(); void requestRender(); + void onAboutToQuit(); private: QObject* finishQmlLoad(std::function f); From c07f3789e4e1d954225bd91f3e38ec33e43accc8 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 22 Feb 2016 14:26:33 -0800 Subject: [PATCH 3/3] Don't crash on script destructor --- libraries/script-engine/src/ScriptEngine.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a65fe7417d..738e313f8f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -144,7 +144,12 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam ScriptEngine::~ScriptEngine() { qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename(); - DependencyManager::get()->removeScriptEngine(this); + auto scriptEngines = DependencyManager::get(); + if (scriptEngines) { + scriptEngines->removeScriptEngine(this); + } else { + qCWarning(scriptengine) << "Script destroyed after ScriptEngines!"; + } } void ScriptEngine::disconnectNonEssentialSignals() {