1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-14 13:41:12 +00:00

fix deadlock between PilelineHashMapRD::local_mutex and GDScriptCache::mutex

This commit is contained in:
100gold
2025-03-10 03:37:57 +03:00
parent b5bdb88062
commit 477b6451a0

View File

@@ -77,9 +77,16 @@ private:
} }
void _wait_for_all_pipelines() { void _wait_for_all_pipelines() {
thread_local LocalVector<WorkerThreadPool::TaskID> tasks_to_wait;
{
MutexLock local_lock(local_mutex); MutexLock local_lock(local_mutex);
for (KeyValue<uint32_t, WorkerThreadPool::TaskID> key_value : compilation_tasks) { for (KeyValue<uint32_t, WorkerThreadPool::TaskID> key_value : compilation_tasks) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(key_value.value); tasks_to_wait.push_back(key_value.value);
}
}
for (WorkerThreadPool::TaskID task_id : tasks_to_wait) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id);
} }
} }
@@ -137,6 +144,9 @@ public:
} }
void wait_for_pipeline(uint32_t p_key_hash) { void wait_for_pipeline(uint32_t p_key_hash) {
WorkerThreadPool::TaskID task_id_to_wait = WorkerThreadPool::INVALID_TASK_ID;
{
MutexLock local_lock(local_mutex); MutexLock local_lock(local_mutex);
if (!compilation_set.has(p_key_hash)) { if (!compilation_set.has(p_key_hash)) {
// The pipeline was never submitted, we can't wait for it. // The pipeline was never submitted, we can't wait for it.
@@ -146,11 +156,16 @@ public:
HashMap<uint32_t, WorkerThreadPool::TaskID>::Iterator task_it = compilation_tasks.find(p_key_hash); HashMap<uint32_t, WorkerThreadPool::TaskID>::Iterator task_it = compilation_tasks.find(p_key_hash);
if (task_it != compilation_tasks.end()) { if (task_it != compilation_tasks.end()) {
// Wait for and remove the compilation task if it exists. // Wait for and remove the compilation task if it exists.
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_it->value); task_id_to_wait = task_it->value;
compilation_tasks.remove(task_it); compilation_tasks.remove(task_it);
} }
} }
if (task_id_to_wait != WorkerThreadPool::INVALID_TASK_ID) {
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_id_to_wait);
}
}
// Retrieve a pipeline. It'll return an empty pipeline if it's not available yet, but it'll be guaranteed to succeed if 'wait for compilation' is true and stall as necessary. Source is just an optional number to aid debugging. // Retrieve a pipeline. It'll return an empty pipeline if it's not available yet, but it'll be guaranteed to succeed if 'wait for compilation' is true and stall as necessary. Source is just an optional number to aid debugging.
RID get_pipeline(const Key &p_key, uint32_t p_key_hash, bool p_wait_for_compilation, RS::PipelineSource p_source) { RID get_pipeline(const Key &p_key, uint32_t p_key_hash, bool p_wait_for_compilation, RS::PipelineSource p_source) {
RBMap<uint32_t, RID>::Element *e = hash_map.find(p_key_hash); RBMap<uint32_t, RID>::Element *e = hash_map.find(p_key_hash);