summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2023-02-26 17:17:41 +0100
committerPedro J. Estébanez <pedrojrulez@gmail.com>2023-02-26 17:19:48 +0100
commitb60197d1c6a88bd9944a43e3e800c04641a918d1 (patch)
treefa2dacf5873502770c524312bd119383c090e0c3 /core
parent1bd0b296e195a622c362a12d8e3dca51e8648578 (diff)
Fix deadlock in cyclic resource load
Diffstat (limited to 'core')
-rw-r--r--core/io/resource_loader.cpp27
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