godotengine / godotengine/godot

CustomCallables keep a references to an old free_func on hotreload

Open
#105,802 11 comments 5 reactions 0 assignees View on GitHub
bug topic:core topic:gdextension
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

Godot 4.4 dafc4739

### System information

linux

### Issue description

When creating a custom callable, and connecting it to a node, if the extension from which the callable was create gets reloaded (hotreload), the editor may/will crash.

I tracked it down to the `free_func` called [here](https://github.com/godotengine/godot/blob/dafc47390c39a6be75cf1705f527ccc1b38a32b0/core/extension/gdextension_interface.cpp#L234) _(but i guess any other `ffi_func` would do the trick)_
i've added `WARN_PRINT` around it (on a local copy of this commit) and it clearly crashes calling it
```cpp
~CallableCustomExtension() {
WARN_PRINT("before free");
if (free_func != nullptr) {
free_func(userdata);
}
WARN_PRINT("after free");
}
```
I get this output on the terminal (trying to reload the project after recompiling)
```bash
Building for architecture x86_64 on platform linux
scons: done reading SConscript files.
scons: Building targets ...
scons: `godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a' is up to date.
Compiling shared src/example.cpp ...
Linking Shared Library demo/bin/libgdexample.linux.template_debug.x86_64.so ...
scons: done building targets.
WARNING: before free
at: ~CallableCustomExtension (core/extension/gdextension_interface.cpp:233)
*** stack smashing detected ***: terminated
```

the problematic lines on the example (which is one of the [tests from godot-cpp](https://github.com/godotengine/godot-cpp/blob/master/test/src/example.cpp) with some light tweaking) is [this one](https://github.com/Ventilador/callable-crash/blob/0fb623112e508ebb14519e4a35aa05160b2cc796/src/example.cpp#L25) (having a destructor)

and [this one](https://github.com/Ventilador/callable-crash/blob/0fb623112e508ebb14519e4a35aa05160b2cc796/src/example.cpp#L117) (registering the callable on `this`)

it may be related to [this gdext-rust ticket](https://github.com/godot-rust/gdext/issues/984) or at least it's what it took me to figure out the crashes

### Steps to reproduce

1) Create a custom callable using `callable_custom_create2`
2) Rebuild your extension
3) trigger an editor refresh (with focus so it reloads the extension)
4) either Quit to Project List or Reload Project _(sometimes even changing scene tabs, i think when they where never loaded but the extension was)_

### Minimal reproduction project (MRP)

https://github.com/Ventilador/callable-crash

Contributor guide

Open the contributing guide

Research direction

Start in core/extension/gdextension_interface.cpp around CallableCustomExtension::~CallableCustomExtension and the referenced free_func call. Reproduce with the linked callable-crash MRP using callable_custom_create2, rebuild the extension, and trigger an editor refresh followed by reload or quitting to the project list. Done means the custom callable no longer crashes during extension hot-reload cleanup.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.