Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exporting project in release configuration makes optinal Gd references empty without a debug build #664

Open
lostlont opened this issue Apr 15, 2024 · 2 comments
Labels
bug c: register Register classes, functions and other symbols to GDScript

Comments

@lostlont
Copy link

Steps to reproduce

  1. Have a godot-rust library, a Godot project, and the two linked together with the gdextension file for both debug and release builds.
  2. Have a custom node type in the Rust library with an #[export] other: Option<Gd<Node>> value. Print its value in the ready function.
  3. Build the Rust library for release build and delete any debug build outputs.
  4. Open the Godot project, place a custom node, and any other node. Set up the custom node value to point to the other node.
  5. Delete the .godot folder if it was present from an earlier run.
  6. Export the Godot project in release configuration. Run the binary and observe that the Rust library panics at unwrapping the empty reference value.

System information

Reproduced in a clean minimal project with Godot v4.2.1 on Windows, but I saw it in a normal project in v4.3-dev5 and on Linux too. Tried with gdext@e7cc36 (2024-04-15).

To make sure that it's only the Option<Gd<Node>> that doesn't get its value initialized I added another field with a primitive type like #[export] value: i32 set to non-zero value in the project and that indeed prints its proper value.

Expected output

(From a release build where debug build was also present.)

PS C:\Users\lostlont\Desktop\godot-rust-test\build\windows\release> .\godot-rust-test.exe
PS C:\Users\lostlont\Desktop\godot-rust-test\build\windows\release> Initialize godot-rust (API v4.2.stable.official, runtime v4.2.1.stable.official)
Godot Engine v4.2.1.stable.official.b09f793f5 - https://godotengine.org
Vulkan API 1.3.260 - Forward+ - Using Vulkan Device #0: AMD - Radeon (TM) RX 470 Graphics

value: 42
other.name: TestNode2
value: 43
other.name: TestNode

Actual output

PS C:\Users\lostlont\Desktop\godot-rust-test\build\windows\release> .\godot-rust-test.exe
PS C:\Users\lostlont\Desktop\godot-rust-test\build\windows\release> Initialize godot-rust (API v4.2.stable.official, runtime v4.2.1.stable.official)
Godot Engine v4.2.1.stable.official.b09f793f5 - https://godotengine.org
Vulkan API 1.3.260 - Forward+ - Using Vulkan Device #0: AMD - Radeon (TM) RX 470 Graphics

value: 42
thread '<unnamed>' panicked at src\lib.rs:43:14:
called `Option::unwrap()` on a `None` value
stack backtrace:
   0:     0x7ffb13af97aa - std::backtrace_rs::backtrace::dbghelp::trace::hacfb2290d6f041d8
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\..\..\backtrace\src\backtrace/dbghelp.rs:131:5
   1:     0x7ffb13af97aa - std::backtrace_rs::backtrace::trace_unsynchronized::hdfe81743a1a02ed5
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\..\..\backtrace\src\backtrace/mod.rs:66:5
   2:     0x7ffb13af97aa - std::sys_common::backtrace::_print_fmt::h7ba8ff6eb3450b74
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\sys_common/backtrace.rs:68:5
   3:     0x7ffb13af97aa - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h419f3866c85fe1bf
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\sys_common/backtrace.rs:44:22
   4:     0x7ffb13b489ad - core::fmt::rt::Argument::fmt::hefb4ad2f61213328
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\core\src\fmt/rt.rs:142:9
   5:     0x7ffb13b489ad - core::fmt::write::h81c90b6a84eba5be
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\core\src\fmt/mod.rs:1120:17
   6:     0x7ffb13aefbdd - std::io::Write::write_fmt::h216459b0e40bea5d
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\io/mod.rs:1846:15
   7:     0x7ffb13af95d3 - std::sys_common::backtrace::_print::h4508c4e8cc70e1aa
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\sys_common/backtrace.rs:47:5
   8:     0x7ffb13af95d3 - std::sys_common::backtrace::print::hea1734d8b31113d5
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\sys_common/backtrace.rs:34:9
   9:     0x7ffb13afc309 - std::panicking::default_hook::{{closure}}::ha8fd0cbe9cc21e6f
  10:     0x7ffb13afc008 - std::panicking::default_hook::hd35fa15eba4e74a2
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src/panicking.rs:292:9
  11:     0x7ffb13afca0f - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::ha685e7d47afbfbfb
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\alloc\src/boxed.rs:2029:9
  12:     0x7ffb13afca0f - std::panicking::rust_panic_with_hook::hca0c0de800db3c83
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src/panicking.rs:785:13
  13:     0x7ffb13afc881 - std::panicking::begin_panic_handler::{{closure}}::he773c37bd73058bd
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src/panicking.rs:651:13
  14:     0x7ffb13af9f49 - std::sys_common::backtrace::__rust_end_short_backtrace::hff55a16a8c27989e
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src\sys_common/backtrace.rs:171:18
  15:     0x7ffb13afc606 - rust_begin_unwind
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\std\src/panicking.rs:647:5
  16:     0x7ffb13b44fb7 - core::panicking::panic_fmt::h678ed93bf965ebf9
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\core\src/panicking.rs:72:14
  17:     0x7ffb13b45072 - core::panicking::panic::h7b26555fedc35695
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\core\src/panicking.rs:144:5
  18:     0x7ffb13b44ce8 - core::option::unwrap_failed::heba8ea2599e810c6
                               at /rustc/25ef9e3d85d934b27d9dada2f9dd52b1dc63bb04/library\core\src/option.rs:1978:5
  19:     0x7ffb1305ea75 - <godot_rust_test::TestNode as godot_core::obj::traits::cap::ImplementsGodotVirtual>::__virtual_call::function::h5a4012fbff537f2d
  20:     0x7ff75d5d07c4 - <unknown>
  21:     0x7ff75b521c34 - <unknown>
  22:     0x7ff75b521be4 - <unknown>
  23:     0x7ff75b556cbe - <unknown>
  24:     0x7ff75a804336 - <unknown>
  25:     0x7ff75dd0ab23 - <unknown>
  26:     0x7ff75a7c12ee - <unknown>
  27:     0x7ff75a7c13e6 - <unknown>
  28:     0x7ffbce707344 - <unknown>
  29:     0x7ffbcf3426b1 - <unknown>
fatal runtime error: failed to initiate panic, error 5

Note that the actual dll copied to the exported folder is the proper release configuration library. It just looks like that references are not initialized when the debug library is not present.

I have the feeling that it's expected to have a debug build of the godot-rust library always, as opening the project in the editor also shows missing components without it, however the export itself seem to be capable of handling the types and primitives of the library so I'd think that it's just malfunctioning right now. Also this may not be a normal use case in the editor, but in CI build pipelines it would be normal to have only a release build job, without any debug build artifacts.

Thank you very much

@Bromeon Bromeon added bug c: register Register classes, functions and other symbols to GDScript labels Apr 15, 2024
@Bromeon
Copy link
Member

Bromeon commented Apr 15, 2024

Thanks for reporting and the detailed description!

Also this may not be a normal use case in the editor, but in CI build pipelines it would be normal to have only a release build job, without any debug build artifacts.

Note that we currently do have a CI run that checks a Rust release build (cargo build --release) and uses a Godot release (non-editor) binary:

- name: linux-release
os: ubuntu-20.04
artifact-name: linux-release-nightly
godot-binary: godot.linuxbsd.template_release.x86_64
rust-extra-args: --release
rust-cache-key: release

And there is also Option<Gd<T>> used, with custom types:

#[derive(GodotClass)]
#[class(init, base=Node)]
pub struct ExportResource {
#[export]
#[var(usage_flags=[DEFAULT, EDITOR_INSTANTIATE_OBJECT])]
pub foo: Option<Gd<CustomResource>>,
#[export]
pub bar: Option<Gd<RenamedCustomResource>>,
}

However, we don't involve the editor here. Does your problem only appear if you set an object from the editor, and then run it? Not if you set it programmatically?

If yes, could you show the persisted scene file (with the other node attached) in both Release/Debug?

@lostlont
Copy link
Author

I assume that it will only appear if I set the reference in the editor, as the nodes themselves are functioning properly so I could probably set any reference to any other node at run-time. I'll try to check this later though.

Here's the scene file I used:

[gd_scene format=3 uid="uid://vmll78trsph2"]

[node name="Node3D" type="Node3D"]

[node name="TestNode" type="TestNode" parent="." node_paths=PackedStringArray("other")]
value = 42
other = NodePath("../TestNode2")

[node name="TestNode2" type="TestNode" parent="." node_paths=PackedStringArray("other")]
value = 43
other = NodePath("../TestNode")

I tried it in the editor manually and from the command line too with godot --headless --verbose --export-release windows ../build/windows/release/godot-rust-test.exe and it produces the same issue. I haven't tried it just by running a Godot project via the Godot engine manually as I can't see any command line options to run instantly in release mode.

I checked your CI script and if I understand it properly then the sed -i'.bak' "s!/debug/!/release/!g" "$dir/rust.gdextension" line in the check-example.sh file actually just replaces the /debug/ folder paths to release paths in the debug library references so each architecture will have both a debug and a release config pointing to the same release library. I tried running my project with a similar gdextension setup and it works in that case. So having a debug config pointing to a release library makes everything run properly. But having separate debug and release file paths and missing the debug library causes the issue in the release build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug c: register Register classes, functions and other symbols to GDScript
Projects
None yet
Development

No branches or pull requests

2 participants