From d77024bbf1f4c9cadb777b36b1ce3ebabf348396 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 22 Apr 2025 16:16:46 +0200 Subject: [PATCH] Fix crash when existing engine while content streaming is active --- Source/Engine/Content/Asset.cpp | 21 +++++++------------ .../Content/Loading/Tasks/LoadAssetDataTask.h | 4 ++++ .../Graphics/Textures/StreamingTexture.cpp | 12 ++++++----- Source/Engine/Threading/Task.cpp | 4 ++-- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Source/Engine/Content/Asset.cpp b/Source/Engine/Content/Asset.cpp index c128a33a0..0d5391482 100644 --- a/Source/Engine/Content/Asset.cpp +++ b/Source/Engine/Content/Asset.cpp @@ -467,11 +467,13 @@ void Asset::CancelStreaming() { // Cancel loading task but go over asset locker to prevent case if other load threads still loads asset while it's reimported on other thread Locker.Lock(); - auto loadTask = (ContentLoadTask*)Platform::AtomicRead(&_loadingTask); + auto loadingTask = (ContentLoadTask*)Platform::AtomicRead(&_loadingTask); Locker.Unlock(); - if (loadTask) + if (loadingTask) { - loadTask->Cancel(); + Platform::AtomicStore(&_loadingTask, 0); + LOG(Warning, "Cancel loading task for \'{0}\'", ToString()); + loadingTask->Cancel(); } } @@ -632,18 +634,11 @@ void Asset::onUnload_MainThread() ASSERT(IsInMainThread()); + // Cancel any streaming before calling OnUnloaded event + CancelStreaming(); + // Send event OnUnloaded(this); - - // Check if is during loading - auto loadingTask = (ContentLoadTask*)Platform::AtomicRead(&_loadingTask); - if (loadingTask != nullptr) - { - // Cancel loading - Platform::AtomicStore(&_loadingTask, 0); - LOG(Warning, "Cancel loading task for \'{0}\'", ToString()); - loadingTask->Cancel(); - } } #if USE_EDITOR diff --git a/Source/Engine/Content/Loading/Tasks/LoadAssetDataTask.h b/Source/Engine/Content/Loading/Tasks/LoadAssetDataTask.h index de0c503bf..5c9ab5604 100644 --- a/Source/Engine/Content/Loading/Tasks/LoadAssetDataTask.h +++ b/Source/Engine/Content/Loading/Tasks/LoadAssetDataTask.h @@ -34,6 +34,10 @@ public: public: // [ContentLoadTask] + String ToString() const override + { + return String::Format(TEXT("Load Asset Data Task ({}, {}, {})"), (int32)GetState(), _chunks, _asset ? _asset->GetPath() : String::Empty); + } bool HasReference(Object* obj) const override { return obj == _asset; diff --git a/Source/Engine/Graphics/Textures/StreamingTexture.cpp b/Source/Engine/Graphics/Textures/StreamingTexture.cpp index 4d1e8bb14..87378ef9d 100644 --- a/Source/Engine/Graphics/Textures/StreamingTexture.cpp +++ b/Source/Engine/Graphics/Textures/StreamingTexture.cpp @@ -322,15 +322,17 @@ class StreamTextureMipTask : public GPUUploadTextureMipTask { private: StreamingTexture* _streamingTexture; + Task* _rootTask; FlaxStorage::LockData _dataLock; public: - StreamTextureMipTask(StreamingTexture* texture, int32 mipIndex) + StreamTextureMipTask(StreamingTexture* texture, int32 mipIndex, Task* rootTask) : GPUUploadTextureMipTask(texture->GetTexture(), mipIndex, Span(nullptr, 0), 0, 0, false) , _streamingTexture(texture) + , _rootTask(rootTask ? rootTask : this) , _dataLock(_streamingTexture->GetOwner()->LockData()) { - _streamingTexture->_streamingTasks.Add(this); + _streamingTexture->_streamingTasks.Add(_rootTask); _texture.Released.Bind(this); } @@ -341,7 +343,7 @@ private: if (_streamingTexture) { ScopeLock lock(_streamingTexture->GetOwner()->GetOwnerLocker()); - _streamingTexture->_streamingTasks.Remove(this); + _streamingTexture->_streamingTasks.Remove(_rootTask); _streamingTexture = nullptr; } } @@ -393,7 +395,7 @@ protected: if (_streamingTexture) { ScopeLock lock(_streamingTexture->GetOwner()->GetOwnerLocker()); - _streamingTexture->_streamingTasks.Remove(this); + _streamingTexture->_streamingTasks.Remove(_rootTask); _streamingTexture = nullptr; } @@ -443,7 +445,7 @@ Task* StreamingTexture::CreateStreamingTask(int32 residency) // Add upload data task const int32 allocatedMipIndex = TotalIndexToTextureMipIndex(mipIndex); - task = New(this, allocatedMipIndex); + task = New(this, allocatedMipIndex, result); if (result) result->ContinueWith(task); else diff --git a/Source/Engine/Threading/Task.cpp b/Source/Engine/Threading/Task.cpp index b4bd5f025..cd36619c9 100644 --- a/Source/Engine/Threading/Task.cpp +++ b/Source/Engine/Threading/Task.cpp @@ -208,8 +208,8 @@ void Task::OnCancel() if (IsRunning()) { // Wait for it a little bit - const double timeout = 2000.0; - LOG(Warning, "Cannot cancel \'{0}\' because it's still running, waiting for end with timeout: {1} ms", ToString(), timeout); + constexpr double timeout = 10000.0; // 10s + LOG(Warning, "Cannot cancel \'{0}\' because it's still running, waiting for end with timeout: {1}ms", ToString(), timeout); Wait(timeout); }