My xlib rust safe wrapper crashes because a variable is dropped too early

I am working on x11/xlib safe bindings for my projects, I have this in my code:

impl Drop for Window {
    fn drop(&mut self) {
        unsafe { XDestroyWindow(self.display, self.id) };
    }
}

However, this causes some problems:

        let event = display.get_event();

        match event.type_ {
            // subwindow is Option<Window>
            EventType::KeyPress(_key_event) => {
                if let Some(_window) = event.subwindow {
                    // This will only happen if the key is pressed inside a Window, and
                    // not the root window in general
                    println!("Return was pressed inside a window!");
                }
            }

        ....

this program for example crashes completely, probably because when I try to check if the window is Some, the subwindow variable is dropped?
This gets printed as soon as I hit the key, and the program crashes

X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  4 (X_DestroyWindow)
  Resource id in failed request:  0xf8
  Serial number of failed request:  13
  Current serial number in output stream:  13

Your wrapped API should distinguish owned objects from non-owned, since that controls when things get destroyed. E.g. I wouldn't expect an event to exclusively own a window.

Edit: Sometimes shared ownership may help. e.g. sometimes it's ok for events to have shared ownership of a window to keep it from being destroyed until all events have been processed. Other times the event loop could be the thing keeping the window alive.

1 Like

So the subwindow can be changed from an Option<Window> to an Option<&Window>?

That's a good way

Who would own the windows then? Do they need to be static?

One approach: if something creates a window then it owns it; when it drops it the window gets destroyed.

Another approach: many things co-own the window. As long as at least one co-owner has it, the window stays alive.