Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gtk causes a segmentation fault along with winit. #2772

Open
tseli0s opened this issue Apr 18, 2023 · 16 comments
Open

Gtk causes a segmentation fault along with winit. #2772

tseli0s opened this issue Apr 18, 2023 · 16 comments
Labels
A - needs repro waiting for a way to reproduce C - needs investigation Issue must be confirmed and researched DS - x11

Comments

@tseli0s
Copy link

tseli0s commented Apr 18, 2023

When I use winit in Rust along with nvdialog-rs I get a segmentation fault, apparently backtracing all the way back to Gtk.
Here's the issue on the NvDialog repo, if it helps,
and here's the backtrace from gdb (NOTE: It's the full backtrace which includes some irrelevant information).

@kchibisov
Copy link
Member

In general, using GTK with other libraries could be troublesome.

I'd suggest to provide at least minimal information, like what display server, operating system, minimal reproducer example, and so on.

@kchibisov kchibisov added C - needs investigation Issue must be confirmed and researched A - needs repro waiting for a way to reproduce labels Apr 18, 2023
@tseli0s
Copy link
Author

tseli0s commented Apr 19, 2023

Here's the system information:

OS: elementaryOS 7 (Based on Ubuntu 22.04)
Display Server: X11
Gtk version: 3.24.33
Xorg version: 1:7.7+23ubuntu2

And this is an example I managed to put together. Be sure to use the second dependency as-is; Don't download from crates.io!

/// Cargo.toml:
///
/// [dependencies]
/// winit = "0.28.3"
/// nvdialog-rs = { git = "https://github.com/tseli0s/nvdialog-rs.git/" }

use nvdialog_rs::DialogBox;
use winit::event::StartCause;

fn main() {
    nvdialog_rs::init().expect("Can't initialize NvDialog.");
    let event_loop = winit::event_loop::EventLoop::new();
    winit::window::Window::new(&event_loop).expect("Can't create window");

    event_loop.run(move |event, _, control_flow|{
            if let winit::event::Event::NewEvents(StartCause::Init) = event {
                DialogBox::new("Title", "This will never be shown", nvdialog_rs::DialogType::Error)
                    .expect("Can't create dialog")
                    .show();
                control_flow.set_exit();
            }
    })
}

(I can also provide a Gtk-only example if this one doesn't work for some reason)

@Diegovsky
Copy link

From the backtrace, seems like it actually comes from Xlib instead of GTK. That makes sense because both libraries are probably using it.

I'm not sure if this is supposed to happen, but it seems winit (rust) moved the static mutex somewhere (?).

Could you try starting gdb and watching that memory location before running?

1 similar comment
@Diegovsky

This comment was marked as duplicate.

@tseli0s
Copy link
Author

tseli0s commented Apr 24, 2023

From the backtrace, seems like it actually comes from Xlib instead of GTK. That makes sense because both libraries are probably using it.

Basically, Gtk tries to lock some resource in Xlib, or something similar, but that isn't allowed with X11, that's what I meant. Anyway, I found a reddit thread with the exact same issue:

https://www.reddit.com/r/rust/comments/84k3y2/getting_a_segfault_in_pthread_mutex_lock_with/

So this may help a bit more. Also, for debugging purposes, I tried doing all the "gtk part" in a seperate thread. This apparently gives different results each time, I believe it's basically me exploiting undefined behavior. But it did work sometimes. So there's that.

You told me to watch some memory location, since I'm not used at all with gdb, could you make it simpler? What command should I run?

@ids1024
Copy link
Member

ids1024 commented Apr 24, 2023

This might work better with #2614, if that avoids calling the problematic Xlib APIs.

But in general I would not expect GTK and Winit to work in the same process, and the safe solution here is to run them in different processes.

@tseli0s
Copy link
Author

tseli0s commented Apr 24, 2023

But in general I would not expect GTK and Winit to work in the same process, and the safe solution here is to run them in different processes.

I would like to mention (Apparently I didn't mention it in this issue too, just in the original one), that GLFW works without any problem. That's the main reason I wanted to open this issue, because it can probably be fixed in here too.

@ids1024
Copy link
Member

ids1024 commented Apr 24, 2023

Yeah, though "works" doesn't imply "supported" or "safe". So there may be a risk that it stops working in the future, and I don't think either GTK or GLFW would claim to guarantee this in any way. This is especially problematic if you want the application to work on multiple platforms.

But I'm not too familiar with Xlib or the specific issues you might run into here.

@notgull
Copy link
Member

notgull commented Apr 25, 2023

libX11 uses some locking strategies that are difficult to get right in multithreaded programs. Using libxcb should help in this case.

Although, there are quite a few things we need to use libX11 for, unfortunately (cough cough, GLX, cough cough).

@ids1024
Copy link
Member

ids1024 commented Apr 25, 2023

For GLX at least, GTK4 should default to EGL on X11 where it's available, and you get get Glutin to do the same if you're using it.

(I assume EGL should always work on modern X systems with vaguely normal drivers, when not running X over a network?)

@kchibisov
Copy link
Member

In general you can't use the EGL with GTK, unless the private display extension gets stable in EGL, because it can terminate your display and so on.

@ids1024
Copy link
Member

ids1024 commented Apr 25, 2023

Ah, I wasn't familiar with that. But if if Winit and GTK both open separate connections to the X server with XOpenDisplay or equivalent, wouldn't they get separate EGLDisplays from eglGetPlatformDisplay?

I'm not really that familiar with Xlib, and how it uses global state in a way that could cause issues here. But if I wanted something like this to work I'd definitely try to split it into a separate process.

@tseli0s
Copy link
Author

tseli0s commented Apr 26, 2023

if I wanted something like this to work I'd definitely try to split it into a separate process.

That does have a great chance to work, but as you may understand, new processes inherit their data from the parent process, unless the exec system call is used. But if the latter is done then you probably need a new process everytime you need to do something with Gtk, which would make memory usage skyrocket. At least on Linux, I'm not sure how the BSDs do.

@Diegovsky
Copy link

So this may help a bit more. Also, for debugging purposes, I tried doing all the "gtk part" in a seperate thread. This apparently gives different results each time, I believe it's basically me exploiting undefined behavior. But it did work sometimes. So there's that.

You probably can't do that because of some main thread GUI restrictions. I don't know how to proceed. Maybe gtk can initialize itself using an existing x11 connection?

@tseli0s
Copy link
Author

tseli0s commented May 6, 2023

Maybe gtk can initialize itself using an existing x11 connection?

I find it extremely unlikely that this is actually possible, or that there's a chance that Gtk devs will implement it. Or that the Gtk devs want to bother with X11 at all now that Wayland is gaining popularity.

@Diegovsky
Copy link

True, unfortunately...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A - needs repro waiting for a way to reproduce C - needs investigation Issue must be confirmed and researched DS - x11
Development

No branches or pull requests

6 participants