Merge pull request #7155 from jherico/script_engine_crash

Fix a number of crashes / hangs on exit
This commit is contained in:
Clément Brisset 2016-02-22 16:17:33 -08:00
commit 965d6bb006
4 changed files with 28 additions and 7 deletions

View file

@ -260,10 +260,22 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest netRequest(url); QNetworkRequest netRequest(url);
QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest); 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 QEventLoop loop; // Create an event loop that will quit when we get the finished signal
QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit())); QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec(); // Nothing is going to happen on this whole run thread until we get this 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. return netReply; // trying to sync later on.
} }

View file

@ -315,6 +315,8 @@ OffscreenQmlSurface::OffscreenQmlSurface() {
} }
OffscreenQmlSurface::~OffscreenQmlSurface() { OffscreenQmlSurface::~OffscreenQmlSurface() {
QObject::disconnect(&_updateTimer);
QObject::disconnect(qApp);
_renderer->stop(); _renderer->stop();
delete _rootItem; delete _rootItem;
delete _renderer; delete _renderer;
@ -322,6 +324,10 @@ OffscreenQmlSurface::~OffscreenQmlSurface() {
delete _qmlEngine; delete _qmlEngine;
} }
void OffscreenQmlSurface::onAboutToQuit() {
QObject::disconnect(&_updateTimer);
}
void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
_renderer = new OffscreenQmlRenderer(this, shareContext); _renderer = new OffscreenQmlRenderer(this, shareContext);
_renderer->_renderControl->_renderWindow = _proxyWindow; _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, // 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. // a timer with a small interval is used to get better performance.
_updateTimer.setInterval(MIN_TIMER_MS); _updateTimer.setInterval(MIN_TIMER_MS);
connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); QObject::connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]{ QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &OffscreenQmlSurface::onAboutToQuit);
disconnect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
});
_updateTimer.start(); _updateTimer.start();
_qmlComponent = new QQmlComponent(_qmlEngine); _qmlComponent = new QQmlComponent(_qmlEngine);
_qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); _qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
} }

View file

@ -74,6 +74,7 @@ signals:
public slots: public slots:
void requestUpdate(); void requestUpdate();
void requestRender(); void requestRender();
void onAboutToQuit();
private: private:
QObject* finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f); QObject* finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f);

View file

@ -144,7 +144,12 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
ScriptEngine::~ScriptEngine() { ScriptEngine::~ScriptEngine() {
qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename(); qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename();
DependencyManager::get<ScriptEngines>()->removeScriptEngine(this); auto scriptEngines = DependencyManager::get<ScriptEngines>();
if (scriptEngines) {
scriptEngines->removeScriptEngine(this);
} else {
qCWarning(scriptengine) << "Script destroyed after ScriptEngines!";
}
} }
void ScriptEngine::disconnectNonEssentialSignals() { void ScriptEngine::disconnectNonEssentialSignals() {