godot-rust / godot-rust/gdext

`gdext`-based custom resource format tools needs `experimental-threads` feature

Open
#597 2 comments 3 reactions 0 assignees View on GitHub
bug c: engine c: threads
Dominant language
Rust
Stars
5.2k
Forks
312
Avg merge
12h 59m
Merged PRs (30d)
9

Description

To handle custom Resource formats, one needs to define `ResourceFormatSaver` and `ResourceFormatLoader`, and register them with `ResourceSaver::add_resource_format_saver()` and `ResourceLoader::add_resource_format_loader()` for the formats to be recognizable by Godot.

Unbeknownst to the user, registered GodotClasses can be used by Godot outside of the main thread, and it happens only when opening the project in the Godot Editor (or just on `InitLevel::Editor` - as the same happens also during export). Currently, I can confirm only usage of `ResourceFormatLoader` methods, but I can't say for sure that any other calls won't be made.

Methods in question:
- `ResourceFormatLoader::get_resource_uid()`
- `ResourceFormatLoader::get_recognized_extensions()`
- `ResourceFormatLoader::get_resource_type()`

After thread-hardening with additional checks in #581, in practice, it means that any `gdext`-based project that provides `ResourceFormatLoader` will panic without the `experimental-threads` feature enabled.

Will try to provide a minimal example at a further date, currently I paste below the output produced by the locally-modified `gd-props` integration testing project.

- While running the empty scene without entering Godot Editor in any way:
```
$ godot --headless --path tests/godot
Initialize godot-rust (API v4.2.stable.official, runtime v4.2.stable.official)
Godot Engine v4.2.stable.official.46dc27791 - https://godotengine.org

Thread: 1 ResourceFormatLoader::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
```

- While running headless editor with `--quit` option (and during project export outputs seems to be analogous - `EditorExportPlugin` itself is running only on the main thread)

```
$ godot --headless --path tests/godot -e --quit
Initialize godot-rust (API v4.2.stable.official, runtime v4.2.stable.official)
Godot Engine v4.2.stable.official.46dc27791 - https://godotengine.org

Thread: 1 ResourceFormatLoader::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
WARNING: Custom cursor shape not supported by this display server.
at: cursor_set_custom_image (servers/display_server.cpp:505)
Thread: 1 ResourceFormatSaver::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::get_recognized_extensions()
Thread: 14 ResourceFormatLoader::get_resource_uid()
Thread: 14 ResourceFormatLoader::get_recognized_extensions()
Thread: 14 ResourceFormatLoader::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
```

- While opening project in editor with GUI, without insta-quit
```
$ godot --path tests/godot -e
Initialize godot-rust (API v4.2.stable.official, runtime v4.2.stable.official)
Godot Engine v4.2.stable.official.46dc27791 - https://godotengine.org
/lib/x86_64-linux-gnu/libxkbcommon.so.0: undefined symbol: xkb_utf32_to_keysym
/lib/x86_64-linux-gnu/libxkbcommon.so.0: undefined symbol: xkb_keymap_key_get_mods_for_level
OpenGL API 4.6 (Core Profile) Mesa 21.2.6 - Compatibility - Using Device: Intel - Mesa Intel(R) HD Graphics 520 (SKL GT2)

Thread: 1 ResourceFormatLoader::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatSaver::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::get_recognized_extensions()
Thread: 16 ResourceFormatLoader::get_resource_uid()
Thread: 16 ResourceFormatLoader::get_recognized_extensions()
Thread: 16 ResourceFormatLoader::get_recognized_extensions()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 1 ResourceFormatLoader::handles_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
Thread: 17 ResourceFormatLoader::get_resource_type()
```

Browsing the project in the editor while some testing, all the methods seem to be called from the main thread.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.