mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 18:06:57 +02:00
Fix script-related crashes on exiting domain
This commit is contained in:
parent
9503fae612
commit
9e26146a08
3 changed files with 61 additions and 50 deletions
|
@ -220,8 +220,11 @@ void EntityTreeRenderer::setupEntityScriptEngineSignals(const ScriptManagerPoint
|
||||||
void EntityTreeRenderer::resetPersistentEntitiesScriptEngine() {
|
void EntityTreeRenderer::resetPersistentEntitiesScriptEngine() {
|
||||||
// This runs script engine shutdown procedure in a separate thread, avoiding a deadlock when script engine is doing
|
// This runs script engine shutdown procedure in a separate thread, avoiding a deadlock when script engine is doing
|
||||||
// a blocking call to main thread
|
// a blocking call to main thread
|
||||||
if (_persistentEntitiesScriptManager) {
|
ScriptManagerPointer scriptManager = _persistentEntitiesScriptManager;
|
||||||
QtConcurrent::run([manager = _persistentEntitiesScriptManager] {
|
// Clear the pointer before lambda is run on another thread.
|
||||||
|
_persistentEntitiesScriptManager.reset();
|
||||||
|
if (scriptManager) {
|
||||||
|
QtConcurrent::run([manager = scriptManager] {
|
||||||
manager->unloadAllEntityScripts(true);
|
manager->unloadAllEntityScripts(true);
|
||||||
manager->stop();
|
manager->stop();
|
||||||
manager->waitTillDoneRunning();
|
manager->waitTillDoneRunning();
|
||||||
|
@ -251,8 +254,11 @@ void EntityTreeRenderer::resetPersistentEntitiesScriptEngine() {
|
||||||
void EntityTreeRenderer::resetNonPersistentEntitiesScriptEngine() {
|
void EntityTreeRenderer::resetNonPersistentEntitiesScriptEngine() {
|
||||||
// This runs script engine shutdown procedure in a separate thread, avoiding a deadlock when script engine is doing
|
// This runs script engine shutdown procedure in a separate thread, avoiding a deadlock when script engine is doing
|
||||||
// a blocking call to main thread
|
// a blocking call to main thread
|
||||||
if (_nonPersistentEntitiesScriptManager) {
|
ScriptManagerPointer scriptManager = _nonPersistentEntitiesScriptManager;
|
||||||
QtConcurrent::run([manager = _nonPersistentEntitiesScriptManager] {
|
// Release the pointer as soon as possible.
|
||||||
|
_nonPersistentEntitiesScriptManager.reset();
|
||||||
|
if (scriptManager) {
|
||||||
|
QtConcurrent::run([manager = scriptManager] {
|
||||||
manager->unloadAllEntityScripts(true);
|
manager->unloadAllEntityScripts(true);
|
||||||
manager->stop();
|
manager->stop();
|
||||||
manager->waitTillDoneRunning();
|
manager->waitTillDoneRunning();
|
||||||
|
|
|
@ -427,7 +427,10 @@ void ScriptManager::runInThread() {
|
||||||
|
|
||||||
void ScriptManager::executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type ) {
|
void ScriptManager::executeOnScriptThread(std::function<void()> function, const Qt::ConnectionType& type ) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "executeOnScriptThread", type, Q_ARG(std::function<void()>, function));
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
|
manager->executeOnScriptThread(function, type);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,10 +862,10 @@ void ScriptManager::removeEventHandler(const EntityItemID& entityID, const QStri
|
||||||
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::removeEventHandler() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||||
"entityID:" << entityID << " eventName:" << eventName;
|
"entityID:" << entityID << " eventName:" << eventName;
|
||||||
#endif
|
#endif
|
||||||
QMetaObject::invokeMethod(this, "removeEventHandler",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const QString&, eventName),
|
manager->removeEventHandler(entityID, eventName, handler);
|
||||||
Q_ARG(const ScriptValue&, handler));
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
@ -906,10 +909,10 @@ void ScriptManager::addEventHandler(const EntityItemID& entityID, const QString&
|
||||||
"entityID:" << entityID << " eventName:" << eventName;
|
"entityID:" << entityID << " eventName:" << eventName;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "addEventHandler",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const QString&, eventName),
|
manager->addEventHandler(entityID, eventName, handler);
|
||||||
Q_ARG(const ScriptValue&, handler));
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
@ -1168,7 +1171,10 @@ void ScriptManager::stop(bool marshal) {
|
||||||
_isStopping = true; // this can be done on any thread
|
_isStopping = true; // this can be done on any thread
|
||||||
|
|
||||||
if (marshal) {
|
if (marshal) {
|
||||||
QMetaObject::invokeMethod(this, "stop");
|
// Lambda is necessary there to keep shared_ptr counter above zero if this gets called from different thread
|
||||||
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
|
manager->stop(false);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2012,11 +2018,10 @@ bool ScriptManager::hasEntityScriptDetails(const EntityItemID& entityID) const {
|
||||||
|
|
||||||
void ScriptManager::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) {
|
void ScriptManager::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "loadEntityScript",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const QString&, entityScript),
|
manager->loadEntityScript(entityID, entityScript, forceRedownload);
|
||||||
Q_ARG(bool, forceRedownload)
|
});
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PROFILE_RANGE(script, __FUNCTION__);
|
PROFILE_RANGE(script, __FUNCTION__);
|
||||||
|
@ -2093,13 +2098,10 @@ void ScriptManager::entityScriptContentAvailable(const EntityItemID& entityID, c
|
||||||
<< contents << "isURL:" << isURL << "success:" << success;
|
<< contents << "isURL:" << isURL << "success:" << success;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "entityScriptContentAvailable",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const QString&, scriptOrURL),
|
manager->entityScriptContentAvailable(entityID, scriptOrURL, contents, isURL, success, status);
|
||||||
Q_ARG(const QString&, contents),
|
});
|
||||||
Q_ARG(bool, isURL),
|
|
||||||
Q_ARG(bool, success),
|
|
||||||
Q_ARG(const QString&, status));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2443,9 +2445,10 @@ void ScriptManager::unloadEntityScript(const EntityItemID& entityID, bool should
|
||||||
"entityID:" << entityID;
|
"entityID:" << entityID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "unloadEntityScript",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(bool, shouldRemoveFromMap));
|
manager->unloadEntityScript(entityID, shouldRemoveFromMap);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
@ -2496,8 +2499,10 @@ void ScriptManager::unloadAllEntityScripts(bool blockingCall) {
|
||||||
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::unloadAllEntityScripts() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]";
|
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::unloadAllEntityScripts() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "]";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "unloadAllEntityScripts",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
blockingCall ? Qt::BlockingQueuedConnection : Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
|
manager->unloadAllEntityScripts(blockingCall ? Qt::BlockingQueuedConnection : Qt::QueuedConnection);
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
@ -2590,12 +2595,10 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q
|
||||||
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
qCDebug(scriptengine) << "*** WARNING *** ScriptManager::callEntityScriptMethod() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] "
|
||||||
"entityID:" << entityID << "methodName:" << methodName;
|
"entityID:" << entityID << "methodName:" << methodName;
|
||||||
#endif
|
#endif
|
||||||
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
manager->callEntityScriptMethod(entityID, methodName, params, remoteCallerID);
|
||||||
Q_ARG(const QString&, methodName),
|
});
|
||||||
Q_ARG(const QStringList&, params),
|
|
||||||
Q_ARG(const QUuid&, remoteCallerID));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
@ -2660,10 +2663,10 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q
|
||||||
"entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
|
"entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const QString&, methodName),
|
manager->callEntityScriptMethod(entityID, methodName, event);
|
||||||
Q_ARG(const PointerEvent&, event));
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
@ -2699,11 +2702,10 @@ void ScriptManager::callEntityScriptMethod(const EntityItemID& entityID, const Q
|
||||||
"entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
|
"entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "callEntityScriptMethod",
|
// Lambda is necessary there to keep shared_ptr counter above zero
|
||||||
Q_ARG(const EntityItemID&, entityID),
|
QMetaObject::invokeMethod(this, [=, manager = shared_from_this()]{
|
||||||
Q_ARG(const QString&, methodName),
|
manager->callEntityScriptMethod(entityID, methodName, otherID, collision);
|
||||||
Q_ARG(const EntityItemID&, otherID),
|
});
|
||||||
Q_ARG(const Collision&, collision));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef THREAD_DEBUGGING
|
#ifdef THREAD_DEBUGGING
|
||||||
|
|
|
@ -378,8 +378,11 @@ public:
|
||||||
Q_ENUM(Type);
|
Q_ENUM(Type);
|
||||||
|
|
||||||
static int processLevelMaxRetries;
|
static int processLevelMaxRetries;
|
||||||
ScriptManager(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine"));
|
private:
|
||||||
~ScriptManager();
|
// Constructor is private so that only properly generated shared pointer can be used
|
||||||
|
explicit ScriptManager(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine"));
|
||||||
|
public:
|
||||||
|
~ScriptManager() override;
|
||||||
|
|
||||||
// static initialization support
|
// static initialization support
|
||||||
typedef void (*ScriptManagerInitializer)(ScriptManager*);
|
typedef void (*ScriptManagerInitializer)(ScriptManager*);
|
||||||
|
@ -387,7 +390,7 @@ public:
|
||||||
public:
|
public:
|
||||||
ScriptManagerInitializer init;
|
ScriptManagerInitializer init;
|
||||||
StaticInitializerNode* prev;
|
StaticInitializerNode* prev;
|
||||||
inline StaticInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticInitializer(this); }
|
inline explicit StaticInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticInitializer(this); }
|
||||||
};
|
};
|
||||||
static void registerNewStaticInitializer(StaticInitializerNode* dest);
|
static void registerNewStaticInitializer(StaticInitializerNode* dest);
|
||||||
|
|
||||||
|
@ -395,7 +398,7 @@ public:
|
||||||
public:
|
public:
|
||||||
ScriptManagerInitializer init;
|
ScriptManagerInitializer init;
|
||||||
StaticTypesInitializerNode* prev;
|
StaticTypesInitializerNode* prev;
|
||||||
inline StaticTypesInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticTypesInitializer(this); }
|
inline explicit StaticTypesInitializerNode(ScriptManagerInitializer&& pInit) : init(std::move(pInit)),prev(nullptr) { registerNewStaticTypesInitializer(this); }
|
||||||
};
|
};
|
||||||
static void registerNewStaticTypesInitializer(StaticTypesInitializerNode* dest);
|
static void registerNewStaticTypesInitializer(StaticTypesInitializerNode* dest);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue