Skip to content

Can't call node function from a thread #83900

Description

@RitleDev

Godot version

4.1

System information

Windows 11, Godot 4.1.2

Issue description

Previously in Godot 4.0.0 it was possible to call functions like "get_children()" or "get_parent()" within a thread without errors (although this method wasn't thread safe I was okay with it because the functions only read data). Now (in Godot 4.1.2), as I try to call those functions an error shows up telling me to use "call_deferred". this doesn't help me solve the problem because call_deferred always returns null and I can't get any data back to the thread.

An example of the error I get:

  <C++ Error>    Condition "!is_readable_from_caller_thread()" is true. Returning: (Vector3())
  <C++ Source>   scene/3d/node_3d.cpp:249 @ get_global_position()

While it helps the code become more thread-safe I suggest to make an option to make this error a warning or simply ignore it in the project settings so that some of my older projects will continue to work in the newer versions.

Am I missing something? I couldn't find any solution other than editing long code structure and losing performance to get rid of the errors.

Steps to reproduce

I added a simple script that shows the issue with a test project:

extends Node2D

# Work-around to get the child node outside of the thread
@onready var child = get_child(0) 

var a: Thread
var b: Thread

func _ready():
	# Case A shows writing and the error when reading
	a = Thread.new()
	a.start(_threaded_func_A)
	
	# Case B shows reading
	b = Thread.new()
	b.start(_threaded_func_B)

func _threaded_func_A():
	# In this case call deferred will work and solve the issue.
	child.call_deferred("set_visible", true)
	
	# Will only work in Godot 4.0.1 (tested)
	print(get_child(0).visible)
	

# Should print the visibilty state but doesn't
func _threaded_func_B():
	# In this case call deferred won't work and require a work-around.
	# The first call deferred will return null.
	print(call_deferred("get_child", 0).call_deferred("get_visible"))

func _exit_tree():
	a.wait_to_finish()
	b.wait_to_finish()

Minimal reproduction project

Test project:

https://filebin.net/dhp7bjgojfjrhvfl

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions