Skip to content

Reentrant on_notification calls during ready cause panic without bind_mut guard #1656

Description

@Johannes0021

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):

on_notification: POST_ENTER_TREE
ready - START
ready - END
on_notification: READY
on_notification: WM_POSITION_CHANGED
#[derive(GodotClass)]
#[class(base = Node, init)]
struct MyNode {
    base: Base<Node>,
}

#[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)]:
#[func(gd_self)]
fn ready(_: Gd<Self>) {
    // ...
}
  1. Solution with self.base_mut() guard:
fn ready(&mut self) {
    let _guard = self.base_mut();
    // ...
}

Outputs summary on macos:

// ...
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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions