diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 7c288334ba..fd7806b82f 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -567,6 +567,7 @@ void EntityScriptServer::addingEntity(const EntityItemID& entityID) { void EntityScriptServer::deletingEntity(const EntityItemID& entityID) { if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptManager) { + // TODO: Check if this is running on script engine thread, otherwise lambda capturing script engine pointer is needed _entitiesScriptManager->unloadEntityScript(entityID, true); } } @@ -584,6 +585,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, bool EntityScriptDetails details; bool isRunning = _entitiesScriptManager->getEntityScriptDetails(entityID, details); if (entity && (forceRedownload || !isRunning || details.scriptText != entity->getServerScripts())) { + // TODO: Check if this is running on script engine thread, otherwise lambda capturing script engine pointer is needed if (isRunning) { _entitiesScriptManager->unloadEntityScript(entityID, true); } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 8fba576616..3951ffbce0 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -288,7 +288,10 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() { EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); if (entityItem && !entityItem->getScript().isEmpty()) { if (!(entityItem->isLocalEntity() || entityItem->isMyAvatarEntity())) { - _nonPersistentEntitiesScriptManager->unloadEntityScript(entityID, true); + auto scriptEnginePtr = _nonPersistentEntitiesScriptManager; + QMetaObject::invokeMethod(scriptEnginePtr.get(), [scriptEnginePtr, entityID]{ + scriptEnginePtr->unloadEntityScript(entityID, true); + }); } } } @@ -1110,7 +1113,9 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { if (_currentEntitiesInside.contains(entityID)) { scriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } - scriptEngine->unloadEntityScript(entityID, true); + QMetaObject::invokeMethod(scriptEngine.get(), [scriptEngine, entityID]{ + scriptEngine->unloadEntityScript(entityID, true); + }); } auto scene = _viewState->getMain3DScene(); @@ -1163,7 +1168,9 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool if (_currentEntitiesInside.contains(entityID)) { scriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } - scriptEngine->unloadEntityScript(entityID); + QMetaObject::invokeMethod(scriptEngine.get(), [scriptEngine, entityID]{ + scriptEngine->unloadEntityScript(entityID); + }); } entity->scriptHasUnloaded(); } diff --git a/libraries/script-engine/src/ScriptManager.cpp b/libraries/script-engine/src/ScriptManager.cpp index 23122cc302..69d39344b0 100644 --- a/libraries/script-engine/src/ScriptManager.cpp +++ b/libraries/script-engine/src/ScriptManager.cpp @@ -381,6 +381,7 @@ ScriptManager::~ScriptManager() { if (_type == ScriptManager::Type::ENTITY_CLIENT) { printf("ScriptManager::~ScriptManager"); } + _isDeleted = true; } void ScriptManager::disconnectNonEssentialSignals() { diff --git a/libraries/script-engine/src/ScriptManager.h b/libraries/script-engine/src/ScriptManager.h index dc368d1430..8bf6880e51 100644 --- a/libraries/script-engine/src/ScriptManager.h +++ b/libraries/script-engine/src/ScriptManager.h @@ -1665,6 +1665,7 @@ protected: friend ScriptManagerPointer newScriptManager(Context context, const QString& scriptContents, const QString& fileNameString); friend class ScriptManagerScriptingInterface; + std::atomic _isDeleted {false}; // This is used for debugging use-after-delete. It happens quite often, so I'm keeping it here for now. }; /**