Fix deadlock between content storage and asset that is being updated during load

#2621
This commit is contained in:
Wojtek Figat
2024-05-20 14:22:03 +02:00
parent 2418167182
commit cfc9f73744
4 changed files with 10 additions and 7 deletions

View File

@@ -187,6 +187,9 @@ Asset::LoadResult Material::load()
#endif
)
{
// Guard file with the lock during shader generation (prevents FlaxStorage::Tick from messing with the file)
auto lock = Storage->Lock();
// Prepare
MaterialGenerator generator;
generator.Error.Bind(&OnGeneratorError);

View File

@@ -252,6 +252,7 @@ void ContentStorageSystem::Job(int32 index)
{
PROFILE_CPU_NAMED("ContentStorage.Job");
const double time = Platform::GetTimeSeconds();
ScopeLock lock(Locker);
for (auto i = StorageMap.Begin(); i.IsNotEnd(); ++i)
{
@@ -271,7 +272,7 @@ void ContentStorageSystem::Job(int32 index)
}
else
{
storage->Tick();
storage->Tick(time);
}
}
}

View File

@@ -1398,19 +1398,18 @@ void FlaxStorage::Dispose()
_version = 0;
}
void FlaxStorage::Tick()
void FlaxStorage::Tick(double time)
{
// Check if chunks are locked
// Skip if file is in use
if (Platform::AtomicRead(&_chunksLock) != 0)
return;
const double now = Platform::GetTimeSeconds();
bool wasAnyUsed = false;
const float unusedDataChunksLifetime = ContentStorageManager::UnusedDataChunksLifetime.GetTotalSeconds();
for (int32 i = 0; i < _chunks.Count(); i++)
{
auto chunk = _chunks.Get()[i];
const bool wasUsed = (now - chunk->LastAccessTime) < unusedDataChunksLifetime;
const bool wasUsed = (time - chunk->LastAccessTime) < unusedDataChunksLifetime;
if (!wasUsed && chunk->IsLoaded())
{
chunk->Unload();
@@ -1418,7 +1417,7 @@ void FlaxStorage::Tick()
wasAnyUsed |= wasUsed;
}
// Release file handles in none of chunks was not used
// Release file handles in none of chunks is in use
if (!wasAnyUsed && Platform::AtomicRead(&_chunksLock) == 0)
{
CloseFileHandles();

View File

@@ -416,7 +416,7 @@ public:
/// <summary>
/// Ticks this instance.
/// </summary>
void Tick();
void Tick(double time);
#if USE_EDITOR
void OnRename(const StringView& newPath);