diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2f9a151c2f..f9470782bf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2708,6 +2708,7 @@ void Application::cleanupBeforeQuit() { } getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + getEntities()->clear(); // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) QThreadPool::globalInstance()->clear(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 1ecbcb0c8b..8671b3da7e 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -256,18 +256,28 @@ void EntityTreeRenderer::clear() { } // reset the engine - if (_wantScripts && !_shuttingDown) { - resetEntitiesScriptEngine(); - } - // remove all entities from the scene auto scene = _viewState->getMain3DScene(); - if (scene) { - for (const auto& entry : _entitiesInScene) { - const auto& renderer = entry.second; - fadeOutRenderable(renderer); + if (_shuttingDown) { + if (scene) { + render::Transaction transaction; + for (const auto& entry : _entitiesInScene) { + const auto& renderer = entry.second; + renderer->removeFromScene(scene, transaction); + } + scene->enqueueTransaction(transaction); } } else { - qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown"; + if (_wantScripts) { + resetEntitiesScriptEngine(); + } + if (scene) { + for (const auto& entry : _entitiesInScene) { + const auto& renderer = entry.second; + fadeOutRenderable(renderer); + } + } else { + qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene"; + } } _entitiesInScene.clear(); _renderablesToUpdate.clear(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 3b615ba467..5b5fc08460 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -7,6 +7,7 @@ // #include "RenderableWebEntityItem.h" +#include #include #include @@ -46,7 +47,7 @@ static uint64_t MAX_NO_RENDER_INTERVAL = 30 * USECS_PER_SECOND; static uint8_t YOUTUBE_MAX_FPS = 30; // Don't allow more than 20 concurrent web views -static uint32_t _currentWebCount { 0 }; +static std::atomic _currentWebCount(0); static const uint32_t MAX_CONCURRENT_WEB_VIEWS = 20; static QTouchDevice _touchDevice; @@ -356,16 +357,15 @@ void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const Q void WebEntityRenderer::destroyWebSurface() { QSharedPointer webSurface; - ContentType contentType = ContentType::NoContent; withWriteLock([&] { webSurface.swap(_webSurface); - _contentType = contentType; - }); + _contentType = ContentType::NoContent; - if (webSurface) { - --_currentWebCount; - WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections); - } + if (webSurface) { + --_currentWebCount; + WebEntityRenderer::releaseWebSurface(webSurface, _cachedWebSurface, _connections); + } + }); } glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) const { @@ -469,6 +469,12 @@ void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) { QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } +void WebEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) { + // HACK: destroyWebSurface() here to avoid a crash on shutdown. + // TODO: fix the real problem: EntityRenderer<>::dtor never called on shutdown for smart-pointer resource leak. + destroyWebSurface(); +} + void WebEntityRenderer::setProxyWindow(QWindow* proxyWindow) { withReadLock([&] { if (_webSurface) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 7118774d30..6cda1601c8 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -64,6 +64,7 @@ protected: void handlePointerEventAsTouch(const PointerEvent& event); void handlePointerEventAsMouse(const PointerEvent& event); + void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override; private: void onTimeout(); void buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL); diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 0748790df9..b40de7e42a 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -343,4 +343,4 @@ PulsePropertyGroup WebEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; }); -} \ No newline at end of file +}