Fix potential hang on exit due to deadlocks.

This commit is contained in:
Relintai 2025-02-08 11:24:42 +01:00
parent c85768ae8a
commit 12214cb8c7
3 changed files with 48 additions and 0 deletions

View File

@ -172,6 +172,11 @@ void TerrainLibraryMergerPCM::_material_cache_get_key(Ref<TerrainChunk> chunk) {
continue;
}
if (unlikely(_engine_quitting)) {
_material_cache_mutex.unlock();
return;
}
Ref<TerrainSurfaceMerger> nms = ms->duplicate();
nms->set_library(Ref<TerrainLibraryMergerPCM>(this));
nms->set_id(s);
@ -186,6 +191,11 @@ void TerrainLibraryMergerPCM::_material_cache_get_key(Ref<TerrainChunk> chunk) {
continue;
}
if (unlikely(_engine_quitting)) {
_material_cache_mutex.unlock();
return;
}
Ref<Material> nm = m->duplicate();
cache->material_add(nm);
@ -359,6 +369,11 @@ void TerrainLibraryMergerPCM::_liquid_material_cache_get_key(Ref<TerrainChunk> c
continue;
}
if (unlikely(_engine_quitting)) {
_liquid_material_cache_mutex.unlock();
return;
}
Ref<TerrainSurfaceMerger> nms = ms->duplicate();
nms->set_library(Ref<TerrainLibraryMergerPCM>(this));
nms->set_id(s);
@ -373,6 +388,11 @@ void TerrainLibraryMergerPCM::_liquid_material_cache_get_key(Ref<TerrainChunk> c
continue;
}
if (unlikely(_engine_quitting)) {
_liquid_material_cache_mutex.unlock();
return;
}
Ref<Material> nm = m->duplicate();
cache->material_add(nm);
@ -560,6 +580,11 @@ void TerrainLibraryMergerPCM::_prop_material_cache_get_key(Ref<TerrainChunk> chu
continue;
}
if (unlikely(_engine_quitting)) {
_prop_material_cache_mutex.unlock();
return;
}
Ref<Material> nm = m->duplicate();
cache->material_add(nm);
@ -972,6 +997,8 @@ void TerrainLibraryMergerPCM::_setup_material_albedo(const int material_index, c
}
TerrainLibraryMergerPCM::TerrainLibraryMergerPCM() {
_engine_quitting = false;
_packer.instance();
_packer->set_texture_flags(Texture::FLAG_MIPMAPS | Texture::FLAG_FILTER);
@ -1046,6 +1073,14 @@ bool TerrainLibraryMergerPCM::process_prop_textures(Ref<PropData> prop) {
}
#endif
void TerrainLibraryMergerPCM::_notification(int p_what) {
switch (p_what) {
case MainLoop::NOTIFICATION_QUITTING: {
_engine_quitting = true;
} break;
}
}
void TerrainLibraryMergerPCM::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_texture_flags"), &TerrainLibraryMergerPCM::get_texture_flags);
ClassDB::bind_method(D_METHOD("set_texture_flags", "flags"), &TerrainLibraryMergerPCM::set_texture_flags);

View File

@ -125,6 +125,7 @@ protected:
bool process_prop_textures(Ref<PropData> prop);
#endif
virtual void _notification(int p_what);
static void _bind_methods();
RBMap<int, Ref<TerrainMaterialCachePCM>> _material_cache;
@ -143,6 +144,12 @@ protected:
Mutex _material_cache_mutex;
Mutex _liquid_material_cache_mutex;
Mutex _prop_material_cache_mutex;
// To fix potential deadlock on quit
// (Materials can't be duplicated after the engine started deinitializing itself)
// The notification that sets this should be immediate, the engine will start deinitialization later
// so materials that already started duplicating should be fine
bool _engine_quitting;
};
#endif

View File

@ -34,6 +34,7 @@
#include "core/containers/hash_set.h"
#include "core/object/message_queue.h"
#include "core/os/main_loop.h"
#include "terrain_chunk.h"
#include "terrain_structure.h"
@ -1429,6 +1430,11 @@ void TerrainWorld::_notification(int p_what) {
}
break;
}
case MainLoop::NOTIFICATION_QUITTING: {
if (_library.is_valid()) {
_library->notification(MainLoop::NOTIFICATION_QUITTING);
}
} break;
}
}