Search code examples
rustsegmentation-faultx11xlib

XNextEvent() in Rust segfaults


A couple months ago, I started writing an X11 window manager in C with Xlib and I'm now trying to rewrite it in Rust. (after all, rust is the future, right?)

This is the code from main.rs that segfaults:

    // event loop
    loop {
        let mut event : *mut XEvent = 0 as *mut XEvent;
        unsafe {
            XNextEvent(DISPLAY, event);
            /*match (*event).type_ {
                CreateNotify => {
                    println!("sdfg");
                }
                _ => {
                    println!("sdfgsdfg");
                }
            }*/
        }
        println!("dsfgsdfg");
    }

Using GDB, I was able to narrow it down to XNextEvent inside the unsafe block. I'm not really sure where to go from there, since it's calling a function /use/lib/libX11.so.6 and I can't list the function to see where it quit.

Before you ask about the unsafe block, I can't put Xlib functions outside of unsafe blocks because they are unsafe functions and the compiler will complain.

The project uses the x11 crate on crates.io.


Solution

  • You are passing a pointer to NULL instead of a pointer to a local variable to be filled by XNextEvent, just as if your C code did:

    XEvent *event = NULL;
    XNextEvent(DISPLAY, event); //crash!
    

    In C, you are probably doing:

    XEvent event;
    XNextEvent(DISPLAY, &event);
    

    But unfortunately you cannot do that directly in Rust because you cannot declare an uninitialized variable:

    let mut event: XEvent;
    XNextEvent(DISPLAY, &mut event); //error: event is not initialized
    

    If XEvent implemented Default you could just default initialize it, but I think it does not.

    For these cases you can use MaybeUninit:

    let event = unsafe {
        let mut event = MaybeUninit::uninit();
        XNextEvent(DISPLAY, event.as_mut_ptr());
        event.assume_init()
    };