godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

Crash when invoking call_deferred in worker thread

Open abcjjy opened this issue 2 years ago • 1 comments

Godot version

v4.1.1.stable.official [bd6af8e0e]

godot-cpp version

4.1.1 1009da4

System information

macOS 13.4.0 - Vulkan (Mobile) - dedicated AMD Radeon Pro 560X - Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz (12 Threads)

Issue description

I'm trying to emit signal from a worker thread in c++. However, it crashes when call_deferred is called. Here is the crash log.

handle_crash: Program crashed with signal 11
  Engine version: Godot Engine v4.1.1.stable.official (bd6af8e0ea69167dd0627f3bd54f9105bda0f8b5)
  Dumping the backtrace. Please include this when reporting the bug to the project developer.
  [1] 1   libsystem_platform.dylib            0x00007ff8103a75ed _sigtramp + 29
  [2] 2   ???                                 0x0000000000000000 0x0 + 0
  [3] Object* ClassDB::creator<ENetConnection>()
  [4] VariantIndexedSetGet_Dictionary::get_indexed_size(Variant const*)
  [5] godot::Object::call_deferred_internal(godot::Variant const**, long long)
  [6] godot::Variant godot::Object::call_deferred<godot::String, double>(godot::StringName const&, godot::String const&, double const&)
  [7] void* std::__1::__thread_proxy[abi:v15006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, godot::NTPRequest::request(godot::String const&, int)::$_0>>(void*)
  [8] 8   libsystem_pthread.dylib             0x00007ff81037a1d3 _pthread_start + 125

Here is the debugger error

E 0:00:02:0011   propagate_notification: Caller thread can't call this function in this node (/root). Use call_deferred() or call_thread_group() instead.
  <C++ Error>    Condition "!is_accessible_from_caller_thread()" is true.
  <C++ Source>   scene/main/node.cpp:2208 @ propagate_notification()

Steps to reproduce

bool NTPRequest::request(const String & host, int timeout)
{
    std::thread t([this, host, timeout]() {
            auto st = requestTime(host.utf8().get_data(), timeout);

            if (st > 0)
                call_deferred(String("emit_signal"), String("request_ok"), st);
            });
    t.detach();
    return true;
}

Minimal reproduction project

N/A

abcjjy avatar Oct 25 '23 00:10 abcjjy

Hi. Did you get how to work with threads? I am trying to make a simple scene transition:

// GDscript
$AnimationPlayer.play('dissolve')
yield($AnimationPlayer, 'animation_finished')
get_tree().change_scene(target)
$AnimationPlayer.play_backwards('dissolve')

// C#
public async void ChangeScene(string target)
  {
    anim.Play("Dissolve");
    await ToSignal(anim, "animation_finished");
    GetTree().ChangeSceneToFile(target);
    anim.PlayBackwards("Dissolve");
  }

Trying to use godot:thread, std::thread, std::async, coroutines (kind of achieved), but godot complains.

chriztheanvill avatar Dec 13 '23 13:12 chriztheanvill