Merge pull request #78977 from RandomShaper/workaround_tls_shutdown
Workaround resource loading crashes due to buggy TLS
This commit is contained in:
commit
cdd2313ba2
|
@ -239,15 +239,15 @@ ResourceLoader::LoadToken::~LoadToken() {
|
||||||
|
|
||||||
Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
|
Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress) {
|
||||||
load_nesting++;
|
load_nesting++;
|
||||||
if (load_paths_stack.size()) {
|
if (load_paths_stack->size()) {
|
||||||
thread_load_mutex.lock();
|
thread_load_mutex.lock();
|
||||||
HashMap<String, ThreadLoadTask>::Iterator E = thread_load_tasks.find(load_paths_stack[load_paths_stack.size() - 1]);
|
HashMap<String, ThreadLoadTask>::Iterator E = thread_load_tasks.find(load_paths_stack->get(load_paths_stack->size() - 1));
|
||||||
if (E) {
|
if (E) {
|
||||||
E->value.sub_tasks.insert(p_path);
|
E->value.sub_tasks.insert(p_path);
|
||||||
}
|
}
|
||||||
thread_load_mutex.unlock();
|
thread_load_mutex.unlock();
|
||||||
}
|
}
|
||||||
load_paths_stack.push_back(p_path);
|
load_paths_stack->push_back(p_path);
|
||||||
|
|
||||||
// Try all loaders and pick the first match for the type hint
|
// Try all loaders and pick the first match for the type hint
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -263,7 +263,7 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load_paths_stack.resize(load_paths_stack.size() - 1);
|
load_paths_stack->resize(load_paths_stack->size() - 1);
|
||||||
load_nesting--;
|
load_nesting--;
|
||||||
|
|
||||||
if (!res.is_null()) {
|
if (!res.is_null()) {
|
||||||
|
@ -296,8 +296,10 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
|
||||||
// Thread-safe either if it's the current thread or a brand new one.
|
// Thread-safe either if it's the current thread or a brand new one.
|
||||||
CallQueue *mq_override = nullptr;
|
CallQueue *mq_override = nullptr;
|
||||||
if (load_nesting == 0) {
|
if (load_nesting == 0) {
|
||||||
|
load_paths_stack = memnew(Vector<String>);
|
||||||
|
|
||||||
if (!load_task.dependent_path.is_empty()) {
|
if (!load_task.dependent_path.is_empty()) {
|
||||||
load_paths_stack.push_back(load_task.dependent_path);
|
load_paths_stack->push_back(load_task.dependent_path);
|
||||||
}
|
}
|
||||||
if (!Thread::is_main_thread()) {
|
if (!Thread::is_main_thread()) {
|
||||||
mq_override = memnew(CallQueue);
|
mq_override = memnew(CallQueue);
|
||||||
|
@ -360,8 +362,11 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
|
||||||
|
|
||||||
thread_load_mutex.unlock();
|
thread_load_mutex.unlock();
|
||||||
|
|
||||||
if (load_nesting == 0 && mq_override) {
|
if (load_nesting == 0) {
|
||||||
memdelete(mq_override);
|
if (mq_override) {
|
||||||
|
memdelete(mq_override);
|
||||||
|
}
|
||||||
|
memdelete(load_paths_stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1170,7 +1175,7 @@ bool ResourceLoader::timestamp_on_load = false;
|
||||||
|
|
||||||
thread_local int ResourceLoader::load_nesting = 0;
|
thread_local int ResourceLoader::load_nesting = 0;
|
||||||
thread_local WorkerThreadPool::TaskID ResourceLoader::caller_task_id = 0;
|
thread_local WorkerThreadPool::TaskID ResourceLoader::caller_task_id = 0;
|
||||||
thread_local Vector<String> ResourceLoader::load_paths_stack;
|
thread_local Vector<String> *ResourceLoader::load_paths_stack;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
thread_local uint32_t SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG>::count = 0;
|
thread_local uint32_t SafeBinaryMutex<ResourceLoader::BINARY_MUTEX_TAG>::count = 0;
|
||||||
|
|
|
@ -182,7 +182,7 @@ private:
|
||||||
|
|
||||||
static thread_local int load_nesting;
|
static thread_local int load_nesting;
|
||||||
static thread_local WorkerThreadPool::TaskID caller_task_id;
|
static thread_local WorkerThreadPool::TaskID caller_task_id;
|
||||||
static thread_local Vector<String> load_paths_stack;
|
static thread_local Vector<String> *load_paths_stack; // A pointer to avoid broken TLS implementations from double-running the destructor.
|
||||||
static SafeBinaryMutex<BINARY_MUTEX_TAG> thread_load_mutex;
|
static SafeBinaryMutex<BINARY_MUTEX_TAG> thread_load_mutex;
|
||||||
static HashMap<String, ThreadLoadTask> thread_load_tasks;
|
static HashMap<String, ThreadLoadTask> thread_load_tasks;
|
||||||
static bool cleaning_tasks;
|
static bool cleaning_tasks;
|
||||||
|
|
Loading…
Reference in New Issue