Reentrant `on_notification` calls during `ready` cause panic without `bind_mut` guard
- 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
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