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

View File

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