godotengine / godotengine/godot

`call_thread_safe()` from main thread to sub thread node runs on the main thread

Open
#102,607 3 comments 0 reactions 0 assignees View on GitHub
discussion documentation topic:core
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

- Reproducible in: 4.4.beta3, 4.3.stable, 4.1.stable

### System information

Godot v4.4.beta3 - Linux Mint 22.1 (Xia) on X11 - X11 display driver, Multi-window, 2 monitors - Vulkan (Mobile) - dedicated NVIDIA GeForce GTX 1050 (nvidia; 550.120) - Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz (6 threads)

### Issue description

Calling [`Node.call_thread_safe()`](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-call-thread-safe) *from* the main thread *to* the sub thread node results in the method called from the main thread, instead of the sub thread.

This only specifically happens on `main thread -> sub thread` request.
`sub thread -> main thread` and `sub thread -> other sub thread` requests work as expected (i.e. deferred to receiving node's thread).

### Steps to reproduce

#### Sample Project
1. Open the sample project in v4.4.beta3 .
1. Run the game, and see the output message.

#### Manual setup
1. Create a scene called `TopScene`, and add this script:
```gdscript
extends Node

var running = false

func _process(_delta: float) -> void:
if !running:
print(name, ": tid=", OS.get_thread_caller_id())
$ChildNode.call_thread_safe("print_my_message")
running = true
```
2. Create a child node `ChildNode` in it, and add this script:
```gdscript
extends Node

func _process(_delta: float) -> void:
pass

func print_my_message() -> void:
print(name, ": called from tid=", OS.get_thread_caller_id())
```
3. Set the `ChildNode`'s `Thread Group` to `Sub Thread`.
4. Set the `TopScene`'s `Thread Group` to `Main Thread`.
* Or leave it as `Inherit`, since default thread group should be set to main thread.
5. Run the game, and see the output message.

#### Output
```
TopScene: tid=1
ChildNode: called from tid=1
```
`$ChildNode.print_my_message()` was called from the main thread (`tid=1`), instead of seperate sub thread.

### Minimal reproduction project (MRP)

[call_thread_safe_issue.tar.gz](https://github.com/user-attachments/files/18723480/call_thread_safe_issue.tar.gz)

Contributor guide

Open the contributing guide

Research direction

Start with the Node.call_thread_safe() entry point and run the linked minimal reproduction project using the documented TopScene and ChildNode thread-group setup. Trace why a main-thread call reaches the sub-thread node on tid=1; done means the child method runs on its sub-thread while the other request directions continue to behave as described.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
game-dev, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.