Skip to content

Commit 2ff6594

Browse files
committed
Fix use condition_variable after free
1 parent e343dbb commit 2ff6594

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

core/io/resource_loader.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
337337
load_task.status = THREAD_LOAD_LOADED;
338338
}
339339

340-
if (load_task.cond_var) {
340+
if (load_task.cond_var && load_task.need_wait) {
341341
load_task.cond_var->notify_all();
342-
memdelete(load_task.cond_var);
343-
load_task.cond_var = nullptr;
344342
}
343+
load_task.need_wait = false;
345344

346345
bool ignoring = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_IGNORE_DEEP;
347346
bool replacing = load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE || load_task.cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE_DEEP;
@@ -716,15 +715,21 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
716715
DEV_ASSERT(wtp_task_err == OK);
717716
thread_load_mutex.lock();
718717
}
719-
} else {
718+
} else if (load_task.need_wait) {
720719
// Loading thread is main or user thread.
721720
if (!load_task.cond_var) {
722721
load_task.cond_var = memnew(ConditionVariable);
723722
}
723+
load_task.awaiters_count++;
724724
do {
725725
load_task.cond_var->wait(p_thread_load_lock);
726726
DEV_ASSERT(thread_load_tasks.has(p_load_token.local_path) && p_load_token.get_reference_count());
727-
} while (load_task.cond_var);
727+
} while (load_task.need_wait);
728+
load_task.awaiters_count--;
729+
if (load_task.awaiters_count == 0) {
730+
memdelete(load_task.cond_var);
731+
load_task.cond_var = nullptr;
732+
}
728733
}
729734
} else {
730735
if (loader_is_wtp) {
@@ -1152,11 +1157,10 @@ void ResourceLoader::clear_thread_load_tasks() {
11521157
if (thread_load_tasks.size()) {
11531158
for (KeyValue<String, ResourceLoader::ThreadLoadTask> &E : thread_load_tasks) {
11541159
if (E.value.status == THREAD_LOAD_IN_PROGRESS) {
1155-
if (E.value.cond_var) {
1160+
if (E.value.cond_var && E.value.need_wait) {
11561161
E.value.cond_var->notify_all();
1157-
memdelete(E.value.cond_var);
1158-
E.value.cond_var = nullptr;
11591162
}
1163+
E.value.need_wait = false;
11601164
none_running = false;
11611165
}
11621166
}

core/io/resource_loader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ class ResourceLoader {
167167
Thread::ID thread_id = 0; // Used if running on an user thread (e.g., simple non-threaded load).
168168
bool awaited = false; // If it's in the pool, this helps not awaiting from more than one dependent thread.
169169
ConditionVariable *cond_var = nullptr; // In not in the worker pool or already awaiting, this is used as a secondary awaiting mechanism.
170+
uint32_t awaiters_count = 0;
171+
bool need_wait = true;
170172
LoadToken *load_token = nullptr;
171173
String local_path;
172174
String remapped_path;

0 commit comments

Comments
 (0)