Skip to content

Lambda that outlives the captured script causes a use-after-free crash upon destruction #122532

Description

@cpl-s-matsuyama

Tested versions

  • Reproducible in: v4.8.dev2.official [7220d45], v4.7.1.stable.official [a13da4f]

System information

Godot v4.6.3.stable - macOS Sequoia (15.7.5) - Multi-window, 2 monitors - Metal (Mobile) - integrated Apple M2 Max (Apple8) - Apple M2 Max (12 threads) - 64.00 GiB memory

Issue description

Connecting a GDScript lambda to a signal on an object that outlives the script
aborts the process at exit:

libc++abi: terminating due to uncaught exception of type std::__1::system_error: recursive_mutex lock failed: Invalid argument

The following stack trace was obtained from the dev build of 3000096.

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x18d0e2388 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x18d11b848 pthread_kill + 296
2   libsystem_c.dylib             	       0x18d024a2c abort + 124
3   libc++abi.dylib               	       0x18d0d1384 abort_message + 132
4   libc++abi.dylib               	       0x18d0bfcd8 demangling_terminate_handler() + 316
5   libobjc.A.dylib               	       0x18cd44de4 _objc_terminate() + 172
6   libc++abi.dylib               	       0x18d0d0698 std::__terminate(void (*)()) + 16
7   libc++abi.dylib               	       0x18d0d3c30 __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88
8   libc++abi.dylib               	       0x18d0d3bd8 __cxa_throw + 92
9   libc++.1.dylib                	       0x18d04b674 std::__1::__throw_system_error[abi:ne190102](std::__1::error_code, char const*) + 92
10  libc++.1.dylib                	       0x18d04b618 std::__1::__throw_system_error(int, char const*) + 32
11  libc++.1.dylib                	       0x18d04d588 std::__1::recursive_mutex::lock() + 40
12  godot.macos.editor.dev.arm64  	       0x10ad75864 std::__1::unique_lock<std::__1::recursive_mutex>::unique_lock[abi:nn200100](std::__1::recursive_mutex&) + 52 (unique_lock.h:40)
13  godot.macos.editor.dev.arm64  	       0x10ad75628 std::__1::unique_lock<std::__1::recursive_mutex>::unique_lock[abi:nn200100](std::__1::recursive_mutex&) + 36 (unique_lock.h:39)
14  godot.macos.editor.dev.arm64  	       0x10ad755f4 MutexLock<MutexImpl<std::__1::recursive_mutex>>::MutexLock(MutexImpl<std::__1::recursive_mutex> const&) + 36 (mutex.h:77)
15  godot.macos.editor.dev.arm64  	       0x10ad7565c MutexLock<MutexImpl<std::__1::recursive_mutex>>::MutexLock(MutexImpl<std::__1::recursive_mutex> const&) + 36 (mutex.h:77)
16  godot.macos.editor.dev.arm64  	       0x10560861c GDScript::UpdatableFuncPtr::~UpdatableFuncPtr() + 132 (gdscript.cpp:1425)
17  godot.macos.editor.dev.arm64  	       0x105608690 GDScript::UpdatableFuncPtr::~UpdatableFuncPtr() + 28 (gdscript.cpp:1421)
18  godot.macos.editor.dev.arm64  	       0x1056f37c8 GDScriptLambdaCallable::~GDScriptLambdaCallable() + 72 (gdscript_lambda_callable.h:67)
19  godot.macos.editor.dev.arm64  	       0x1056f36e4 GDScriptLambdaCallable::~GDScriptLambdaCallable() + 28 (gdscript_lambda_callable.h:67)
20  godot.macos.editor.dev.arm64  	       0x10b07a608 void memdelete<CallableCustom>(CallableCustom*) + 72 (memory.h:166)
21  godot.macos.editor.dev.arm64  	       0x10b07acac Callable::~Callable() + 212 (callable.cpp:441)
22  godot.macos.editor.dev.arm64  	       0x10b07acf0 Callable::~Callable() + 28 (callable.cpp:438)
23  godot.macos.editor.dev.arm64  	       0x10b47f8b4 KeyValue<Callable, Object::SignalData::Slot>::~KeyValue() + 40 (pair.h:64)
24  godot.macos.editor.dev.arm64  	       0x10b47f87c KeyValue<Callable, Object::SignalData::Slot>::~KeyValue() + 28 (pair.h:64)
25  godot.macos.editor.dev.arm64  	       0x10b47f850 HashMapElement<Callable, Object::SignalData::Slot>::~HashMapElement() + 32 (hash_map.h:42)
26  godot.macos.editor.dev.arm64  	       0x10b47f820 HashMapElement<Callable, Object::SignalData::Slot>::~HashMapElement() + 28 (hash_map.h:42)
27  godot.macos.editor.dev.arm64  	       0x10b47f7e4 void memdelete<HashMapElement<Callable, Object::SignalData::Slot>>(HashMapElement<Callable, Object::SignalData::Slot>*) + 64 (memory.h:166)
28  godot.macos.editor.dev.arm64  	       0x10b47f798 DefaultTypedAllocator<HashMapElement<Callable, Object::SignalData::Slot>>::delete_allocation(HashMapElement<Callable, Object::SignalData::Slot>*) + 28 (memory.h:303)
29  godot.macos.editor.dev.arm64  	       0x10b47f73c HashMap<Callable, Object::SignalData::Slot, HashMapHasherDefault, HashMapComparatorDefault<Callable, void>, DefaultTypedAllocator<HashMapElement<Callable, Object::SignalData::Slot>>>::_clear_data() + 72 (hash_map.h:253)
30  godot.macos.editor.dev.arm64  	       0x10b480c50 HashMap<Callable, Object::SignalData::Slot, HashMapHasherDefault, HashMapComparatorDefault<Callable, void>, DefaultTypedAllocator<HashMapElement<Callable, Object::SignalData::Slot>>>::~HashMap() + 36 (hash_map.h:708)
31  godot.macos.editor.dev.arm64  	       0x10b4733e4 HashMap<Callable, Object::SignalData::Slot, HashMapHasherDefault, HashMapComparatorDefault<Callable, void>, DefaultTypedAllocator<HashMapElement<Callable, Object::SignalData::Slot>>>::~HashMap() + 28 (hash_map.h:707)
32  godot.macos.editor.dev.arm64  	       0x10b480564 Object::SignalData::~SignalData() + 32 (object.h:417)
33  godot.macos.editor.dev.arm64  	       0x10b472adc Object::SignalData::~SignalData() + 28 (object.h:417)
34  godot.macos.editor.dev.arm64  	       0x10b481680 KeyValue<StringName, Object::SignalData>::~KeyValue() + 32 (pair.h:64)
35  godot.macos.editor.dev.arm64  	       0x10b481650 KeyValue<StringName, Object::SignalData>::~KeyValue() + 28 (pair.h:64)
36  godot.macos.editor.dev.arm64  	       0x10b481624 HashMapElement<StringName, Object::SignalData>::~HashMapElement() + 32 (hash_map.h:42)
37  godot.macos.editor.dev.arm64  	       0x10b48110c HashMapElement<StringName, Object::SignalData>::~HashMapElement() + 28 (hash_map.h:42)
38  godot.macos.editor.dev.arm64  	       0x10b481788 void memdelete<HashMapElement<StringName, Object::SignalData>>(HashMapElement<StringName, Object::SignalData>*) + 64 (memory.h:166)
39  godot.macos.editor.dev.arm64  	       0x10b48173c DefaultTypedAllocator<HashMapElement<StringName, Object::SignalData>>::delete_allocation(HashMapElement<StringName, Object::SignalData>*) + 28 (memory.h:303)
40  godot.macos.editor.dev.arm64  	       0x10b473298 HashMap<StringName, Object::SignalData, HashMapHasherDefault, HashMapComparatorDefault<StringName, void>, DefaultTypedAllocator<HashMapElement<StringName, Object::SignalData>>>::erase(StringName const&) + 656 (hash_map.h:373)
41  godot.macos.editor.dev.arm64  	       0x10b47d890 Object::~Object() + 452 (object.cpp:2334)
42  godot.macos.editor.dev.arm64  	       0x10b560a58 ProjectSettings::~ProjectSettings() + 268 (project_settings.cpp:1913)
43  godot.macos.editor.dev.arm64  	       0x10b560adc ProjectSettings::~ProjectSettings() + 28 (project_settings.cpp:1909)
44  godot.macos.editor.dev.arm64  	       0x104d89bac void memdelete<ProjectSettings>(ProjectSettings*) + 68 (memory.h:166)
45  godot.macos.editor.dev.arm64  	       0x104d93c24 Main::cleanup(bool) + 960 (main.cpp:5306)
46  godot.macos.editor.dev.arm64  	       0x104cc52a8 OS_MacOS_Headless::run() + 868 (os_macos.mm:1239)
47  godot.macos.editor.dev.arm64  	       0x104d73734 main + 1536 (godot_main_macos.mm:132)
48  dyld                          	       0x18cd7ab98 start + 6076

Steps to reproduce

Run the attached project using the following command:

godot --path [path to MRP]

Minimal reproduction project (MRP)

lambda-callable-exit-crash-mrp.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    For team assessment

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions