Implementing a get_property_list(&mut self) method triggers the main thread check panic
- Dominant language
- Rust
- Stars
- 5.2k
- Forks
- 312
- Avg merge
- 12h 16m
- Merged PRs (30d)
- 11
Description
I'm trying to implement an advanced resource that interacts with the editor, changing its property list at runtime.
After experimenting, I noticed that Godot calls _get_property_list from a different thread, resulting in my program panicking and crashing the engine.
Stacktrace:
```
[panic backtrace]
0: std::backtrace::Backtrace::create
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\std\src\..\..\backtrace\src\backtrace/win64.rs:85:14
1: std::backtrace::Backtrace::capture
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\std\src/backtrace.rs:296:9
2: godot_core::private::set_gdext_hook::{{closure}}
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-core-0.4.3/src/private.rs:320:44
3: std::panicking::panic_with_hook
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\alloc\src/boxed.rs:1999:9
4: std::panicking::panic_handler::{{closure}}
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\std\src/panicking.rs:700:13
5: std::sys::backtrace::__rust_end_short_backtrace
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\std\src\sys/backtrace.rs:174:18
6: __rustc::rust_begin_unwind
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\std\src/panicking.rs:698:5
7: core::panicking::panic_fmt
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb/library\core\src/panicking.rs:75:14
8: godot_ffi::binding::single_threaded::BindingStorage::ensure_main_thread
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-ffi-0.4.3/src/binding/single_threaded.rs:152:17
9: godot_ffi::binding::single_threaded::BindingStorage::get_binding_unchecked
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-ffi-0.4.3/src/binding/single_threaded.rs:124:9
10: godot_ffi::binding::get_binding
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-ffi-0.4.3/src/binding/mod.rs:267:5
11: godot_ffi::binding::get_interface
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-ffi-0.4.3/src/binding/mod.rs:116:6
12: >::from::{{closure}}
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-core-0.4.3/src/builtin/string/string_name.rs:362:17
13: godot_core::builtin::string::string_name::StringName::new_with_string_uninit
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-ffi-0.4.3/src/godot_ffi.rs:199:13
14: >::from
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-core-0.4.3/src/builtin/string/string_name.rs:361:13
15: >::into
at /rustc/ed61e7d7e242494fb7057f2657300d9e77bb4fcb\library\core\src\convert\mod.rs:778:9
16: ::get_property_list
at /mnt/e/clipmap/src/clipmap.rs:26:47
17: ::__godot_get_property_list
at /mnt/e/clipmap/src/clipmap.rs:19:1
18: godot_core::registry::callbacks::get_property_list
at /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-core-0.4.3/src/registry/callbacks.rs:326:25
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
ERROR:
[panic /home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-core-0.4.3/src/storage/mod.rs:38]
Gd::bind_mut() failed, already bound; T = clipmap::clipmap::ClipmapMesh.
Make sure to use `self.base_mut()` instead of `self.to_gd()` when possible.
Details: cannot borrow while accessible mutable borrow exists.
at: godot_core::private::set_gdext_hook::{{closure}} (/home/.../.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/godot-
core-0.4.3/src/private.rs:343)
fatal runtime error: failed to initiate panic, error 5, aborting
```
Relevant part of the code:
```rust
#[godot_api]
impl IPrimitiveMesh for ClipmapMesh {
fn get_property_list(&mut self) -> Vec {
let mut res = Vec::new();
res.push(PropertyInfo{
variant_type: VariantType::INT,
class_id: ClassId::none(),
property_name: "clipmap/number_of_lods".into(),
hint_info: PropertyHintInfo::none(),
usage: PropertyUsageFlags::EDITOR | PropertyUsageFlags::STORAGE,
});
// TODO: add more properties here
res
}
}
```
I am cross-compiling a `dll` from under a WSL terminal using
```bash
$ cargo build --target=x86_64-pc-windows-gnu
```
Adding the `experimental-threads` crate feature fixes this (by removing the check, I presume); but it feels like such basic functionality shouldn't rely on an experimental crate feature.
Contributor guide
Research direction
Start at the get_property_list callback and trace the stack into godot_ffi/binding/single_threaded.rs, especially ensure_main_thread and get_binding. Then inspect the StringName conversion in godot_core/builtin/string/string_name.rs to understand why this callback reaches the main-thread guard. Done means reproducing the editor property-list update without a panic or engine crash, with coverage for the callback path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100