godot-rust / godot-rust/gdext

Reentrant `on_notification` calls during `ready` cause panic without `bind_mut` guard

Open
#1,656 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
5.2k
Forks
312
Avg merge
11h 10m
Merged PRs (30d)
10

Description

The following panics for `aarch64-apple-darwin` (macos) but not for `x86_64-unknown-linux-gnu`
(linux):

Output summary on Linux (maybe because i3, my window manager, defers the position change request):
```text
on_notification: POST_ENTER_TREE
ready - START
ready - END
on_notification: READY
on_notification: WM_POSITION_CHANGED
```

```rust
#[derive(GodotClass)]
#[class(base = Node, init)]
struct MyNode {
base: Base,
}

#[godot_api]
impl INode for MyNode {
fn on_notification(&mut self, what: NodeNotification) {
godot_print!("on_notification: {:?}", what);
}

fn ready(&mut self) {
godot_print!("ready - START");
DisplayServer::singleton().window_set_position(Vector2i::splat(0));
DisplayServer::singleton().window_set_position(Vector2i::splat(1));
godot_print!("ready - END");
}
}
```

While executing `ready`, a `WM_POSITION_CHANGED` notification is emitted synchronously.
This causes a reborrow, resulting in a panic.

---

1. Solution with `#[func(gd_self)]`:
```rust
#[func(gd_self)]
fn ready(_: Gd) {
// ...
}
```

2. Solution with `self.base_mut()` guard:
```rust
fn ready(&mut self) {
let _guard = self.base_mut();
// ...
}
```

Outputs summary on macos:
```text
// ...
on_notification: POST_ENTER_TREE
ready - START
on_notification: WM_POSITION_CHANGED
on_notification: WM_POSITION_CHANGED
ready - END
on_notification: READY
// ...
```

---

It might just be a skill issue on my side but I think it is too easy to shoot yourself in the foot
with this.

Would it be possible to handle this similarly to signal connections, which have the
CONNECT_DEFERRED flag?
The notification does not necessarily need to wait until idle time, it could be deferred only until
the current ready call has finished.
I think this can also happen in other callbacks like process and signal handlers, where
notifications can happen while the callback is still running.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the Rust `MyNode` example on macOS and compare notification behavior with Linux. Trace how `ready`, `on_notification`, `#[func(gd_self)]`, and `base_mut()` interact during synchronous notifications. Done should mean reentrant notifications no longer panic during callbacks, with behavior validated for the reported case and related callback paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
game-dev
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.