diff options
author | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-02-26 17:17:41 +0100 |
---|---|---|
committer | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-02-26 17:19:48 +0100 |
commit | b60197d1c6a88bd9944a43e3e800c04641a918d1 (patch) | |
tree | fa2dacf5873502770c524312bd119383c090e0c3 /core | |
parent | 1bd0b296e195a622c362a12d8e3dca51e8648578 (diff) |
Fix deadlock in cyclic resource load
Diffstat (limited to 'core')
-rw-r--r-- | core/io/resource_loader.cpp | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 22bf8571bf..c47f297a72 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -447,15 +447,24 @@ Ref<Resource> ResourceLoader::load_threaded_get(const String &p_path, Error *r_e ThreadLoadTask &load_task = thread_load_tasks[local_path]; - if (!load_task.cond_var && load_task.status == THREAD_LOAD_IN_PROGRESS) { - // A condition variable was never created for this task. - // That happens when a load has been initiated with subthreads disabled, - // but now another load thread needs to interact with this one (either - // because of subthreads being used this time, or because it's simply a - // threaded load running on a different thread). - // Since we want to be notified when the load ends, we must create the - // condition variable now. - load_task.cond_var = memnew(ConditionVariable); + if (load_task.status == THREAD_LOAD_IN_PROGRESS) { + if (load_task.loader_id == Thread::get_caller_id()) { + // Load is in progress, but it's precisely this thread the one in charge. + // That means this is a cyclic load. + if (r_error) { + *r_error = ERR_BUSY; + } + return Ref<Resource>(); + } else if (!load_task.cond_var) { + // Load is in progress, but a condition variable was never created for it. + // That happens when a load has been initiated with subthreads disabled, + // but now another load thread needs to interact with this one (either + // because of subthreads being used this time, or because it's simply a + // threaded load running on a different thread). + // Since we want to be notified when the load ends, we must create the + // condition variable now. + load_task.cond_var = memnew(ConditionVariable); + } } //cond var still exists, meaning it's still loading, request poll |