Merge pull request #73988 from RandomShaper/fix_cyclic_load_dead_lock

Fix deadlock in cyclic resource load
This commit is contained in:
Rémi Verschelde 2023-02-26 17:35:29 +01:00
commit a12ecd4c95
No known key found for this signature in database
GPG key ID: C3336907360768E1

View file

@ -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]; ThreadLoadTask &load_task = thread_load_tasks[local_path];
if (!load_task.cond_var && load_task.status == THREAD_LOAD_IN_PROGRESS) { if (load_task.status == THREAD_LOAD_IN_PROGRESS) {
// A condition variable was never created for this task. if (load_task.loader_id == Thread::get_caller_id()) {
// That happens when a load has been initiated with subthreads disabled, // Load is in progress, but it's precisely this thread the one in charge.
// but now another load thread needs to interact with this one (either // That means this is a cyclic load.
// because of subthreads being used this time, or because it's simply a if (r_error) {
// threaded load running on a different thread). *r_error = ERR_BUSY;
// Since we want to be notified when the load ends, we must create the }
// condition variable now. return Ref<Resource>();
load_task.cond_var = memnew(ConditionVariable); } 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 //cond var still exists, meaning it's still loading, request poll