Skip to content

The gles/egl backend still segfaults on Wayland when exiting the application. #7665

@meithecatte

Description

@meithecatte

Description
If vulkan is not available on a machine that's running Wayland, the application will crash in eglTerminate. This has previously been thought to have been fixed in #4650, but apparently it is not the case. (I first posted in the thread for that issue, but later realized that this will probably go unnoticed.)

Repro steps
As the examples in the wgpu repo are hitting #5505, I'm providing a reproduction using the examples in the ggez repo instead.

  1. Use a Linux machine running Wayland.
  2. Clone https://github.com/ggez/ggez/ and checkout the devel branch, which at the time of writing makes use of wgpu 25.0.0.
  3. cargo add wgpu --features 'gles,wgsl' --no-default-features
  4. cargo run --example 01_super_simple
  5. Press Escape or otherwise close the window.
  6. Segmentation fault
Backtrace
#0  0x000071b89401d8ac in wl_map_insert_at (map=map@entry=0x5dddbc2bb520, flags=flags@entry=1, i=41, data=<optimized out>) at ../wayland-1.23.1/src/wayland-util.c:290
#1  0x000071b89401da21 in proxy_destroy (proxy=0x5dddbc3d2bb0) at ../wayland-1.23.1/src/wayland-client.c:574
#2  0x000071b89401f7d7 in wl_proxy_destroy_caller_locks (proxy=0x5dddbc3d2bb0) at ../wayland-1.23.1/src/wayland-client.c:598
#3  wl_proxy_marshal_array_flags (proxy=0x5dddbc3d2bb0, opcode=opcode@entry=0, interface=interface@entry=0x0, version=version@entry=4, flags=flags@entry=1, args=args@entry=0x7ffd1ed8bb30) at ../wayland-1.23.1/src/wayland-client.c:943
#4  0x000071b8940203cb in wl_proxy_marshal_flags (proxy=<optimized out>, opcode=0, interface=0x0, version=4, flags=1) at ../wayland-1.23.1/src/wayland-client.c:857
#5  0x000071b887b52a04 in wl_buffer_destroy () at /usr/include/wayland-client-protocol.h:2149
#6  dri2_teardown_wayland () at ../mesa-25.0.4/src/egl/drivers/dri2/platform_wayland.c:3128
#7  0x000071b887b47fe9 in dri2_display_destroy () at ../mesa-25.0.4/src/egl/drivers/dri2/egl_dri2.c:1003
#8  0x000071b887b48659 in dri2_display_release () at ../mesa-25.0.4/src/egl/drivers/dri2/egl_dri2.c:964
#9  dri2_display_release () at ../mesa-25.0.4/src/egl/drivers/dri2/egl_dri2.c:949
#10 dri2_terminate () at ../mesa-25.0.4/src/egl/drivers/dri2/egl_dri2.c:1060
#11 0x000071b887b34dc9 in eglTerminate () at ../mesa-25.0.4/src/egl/main/eglapi.c:780
#12 0x00005ddd80b68ea0 in khronos_egl::{impl#97}::eglTerminate<libloading::safe::Library> (self=0x5dddbc368360, display=0x5dddbc3d1a70) at /home/maya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/khronos-egl-6.0.0/src/lib.rs:2321
#13 khronos_egl::Instance<khronos_egl::Dynamic<libloading::safe::Library, khronos_egl::EGL1_4>>::terminate<khronos_egl::Dynamic<libloading::safe::Library, khronos_egl::EGL1_4>> (self=0x5dddbc368360, display=...)
    at /home/maya/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/khronos-egl-6.0.0/src/lib.rs:1181
#14 0x00005ddd80bd62a6 in wgpu_hal::gles::egl::terminate_display (egl=0x5dddbc368360, display=...) at src/gles/egl.rs:516
#15 0x00005ddd80bd9ce3 in wgpu_hal::gles::egl::{impl#11}::drop (self=0x5dddbc3478e8) at src/gles/egl.rs:733
#16 0x00005ddd80baff87 in core::ptr::drop_in_place<wgpu_hal::gles::egl::Inner> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#17 0x00005ddd80bb158b in core::ptr::drop_in_place<core::cell::UnsafeCell<wgpu_hal::gles::egl::Inner>> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#18 0x00005ddd80baed9f in core::ptr::drop_in_place<lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, wgpu_hal::gles::egl::Inner>> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#19 0x00005ddd80bb027c in core::ptr::drop_in_place<wgpu_hal::gles::egl::Instance> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#20 0x00005ddd80a2cd44 in core::ptr::drop_in_place<alloc::boxed::Box<dyn wgpu_hal::dynamic::instance::DynInstance, alloc::alloc::Global>> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#21 0x00005ddd80a1b95f in core::ptr::drop_in_place<(wgpu_types::Backend, alloc::boxed::Box<dyn wgpu_hal::dynamic::instance::DynInstance, alloc::alloc::Global>)> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#22 0x00005ddd80a1d37e in core::ptr::drop_in_place<[(wgpu_types::Backend, alloc::boxed::Box<dyn wgpu_hal::dynamic::instance::DynInstance, alloc::alloc::Global>)]> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#23 0x00005ddd808a44a3 in alloc::vec::{impl#25}::drop<(wgpu_types::Backend, alloc::boxed::Box<dyn wgpu_hal::dynamic::instance::DynInstance, alloc::alloc::Global>), alloc::alloc::Global> (self=0x5dddbc3c4f88)
    at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3798
#24 0x00005ddd80a1e7c7 in core::ptr::drop_in_place<alloc::vec::Vec<(wgpu_types::Backend, alloc::boxed::Box<dyn wgpu_hal::dynamic::instance::DynInstance, alloc::alloc::Global>), alloc::alloc::Global>> ()
    at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#25 0x00005ddd80a2233c in core::ptr::drop_in_place<wgpu_core::instance::Instance> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#26 0x00005ddd8084a794 in core::ptr::drop_in_place<wgpu_core::global::Global> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#27 0x00005ddd8083ac82 in alloc::sync::Arc<wgpu_core::global::Global, alloc::alloc::Global>::drop_slow<wgpu_core::global::Global, alloc::alloc::Global> (self=0x5dddbcfe9370) at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:1943
#28 0x00005ddd8083b6bd in alloc::sync::{impl#38}::drop<wgpu_core::global::Global, alloc::alloc::Global> (self=0x5dddbcfe9370) at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:2633
#29 0x00005ddd8084c46b in core::ptr::drop_in_place<alloc::sync::Arc<wgpu_core::global::Global, alloc::alloc::Global>> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#30 0x00005ddd8084b934 in core::ptr::drop_in_place<wgpu::backend::wgpu_core::ContextWgpuCore> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#31 0x00005ddd8084adf7 in core::ptr::drop_in_place<wgpu::backend::wgpu_core::CoreBuffer> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#32 0x00005ddd8083a882 in alloc::sync::Arc<wgpu::backend::wgpu_core::CoreBuffer, alloc::alloc::Global>::drop_slow<wgpu::backend::wgpu_core::CoreBuffer, alloc::alloc::Global> (self=0x7ffd1ed8d1c8)
    at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:1943
#33 0x00005ddd8083b2cd in alloc::sync::{impl#38}::drop<wgpu::backend::wgpu_core::CoreBuffer, alloc::alloc::Global> (self=0x7ffd1ed8d1c8) at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:2633
#34 0x00005ddd8084d00b in core::ptr::drop_in_place<alloc::sync::Arc<wgpu::backend::wgpu_core::CoreBuffer, alloc::alloc::Global>> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#35 0x00005ddd8084a879 in core::ptr::drop_in_place<wgpu::dispatch::DispatchBuffer> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#36 0x00005ddd8084a687 in core::ptr::drop_in_place<wgpu::api::buffer::Buffer> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#37 0x00005ddd8061a80c in core::ptr::drop_in_place<ggez::graphics::mesh::Mesh> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#38 0x00005ddd80583eeb in core::ptr::drop_in_place<01_super_simple::MainState> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#39 0x00005ddd805837b9 in core::ptr::drop_in_place<ggez::event::GgezApplicationHandler<01_super_simple::MainState, ggez::context::Context, ggez::error::GameError>> () at /home/maya/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:524
#40 0x00005ddd80593962 in ggez::event::run<01_super_simple::MainState, ggez::context::Context, ggez::error::GameError> (ctx=..., event_loop=..., state=...) at src/event.rs:294
#41 0x00005ddd805b6bb2 in 01_super_simple::main () at examples/01_super_simple.rs:53

Debugging

For more details, try the following:

  1. gdb target/debug/examples/01_super_simple
  2. r
  3. The window shows up.
  4. Ctrl+C in the debugger window
  5. b wl_display_disconnect
  6. b eglTerminate
  7. c
  8. Close the window (it will stay open)
  9. Observe that the wl_display_disconnect window is called first
  10. If desired, obtain a backtrace (bt)
  11. c
  12. Observe that eglTerminate is called after the window has already been disposed of.

This example leads me to believe that this is incorrect sequencing.

Code analysis

I believe that this part of the code might be the culprit:

wgpu/wgpu-hal/src/gles/egl.rs

Lines 997 to 1040 in 50eb207

(Rwh::Wayland(_), raw_window_handle::RawDisplayHandle::Wayland(display_handle)) => {
if inner
.wl_display
.map(|ptr| ptr != display_handle.display.as_ptr())
.unwrap_or(true)
{
/* Wayland displays are not sharable between surfaces so if the
* surface we receive from this handle is from a different
* display, we must re-initialize the context.
*
* See gfx-rs/gfx#3545
*/
log::warn!("Re-initializing Gles context due to Wayland window");
use core::ops::DerefMut;
let display_attributes = [khronos_egl::ATTRIB_NONE];
let display = unsafe {
inner
.egl
.instance
.upcast::<khronos_egl::EGL1_5>()
.unwrap()
.get_platform_display(
EGL_PLATFORM_WAYLAND_KHR,
display_handle.display.as_ptr(),
&display_attributes,
)
}
.unwrap();
let new_inner = Inner::create(
self.flags,
Arc::clone(&inner.egl.instance),
display,
inner.force_gles_minor_version,
)?;
let old_inner = core::mem::replace(inner.deref_mut(), new_inner);
inner.wl_display = Some(display_handle.display.as_ptr());
drop(old_inner);
}
}

From a cursory reading, it would appear that this makes the entire Instance depend on the lifetime of the Window, rather than just the Surface having this dependency. I am lead to believe that, on Wayland, Instance should hold a Box<dyn WindowHandle>, like Surface does. Actually achieving this would be non-trivial, though.

This might be just another symptom of #6211, in which case the best course of action might be simply accepting the segfaults, or manually taking care to hold the window longer than the wgpu Instance and everything that grabs a copy of any relevant Arcs.

Platform
wgpu 25.0.0 (wgpu-core 25.0.1)
mesa 25.0.4
sway 1.10.1 (also tested on KWin)
Arch Linux

We have tested 5 machines. Apart from one where the example fails to initialize (I think it detects that the GL is emulated on top of vulkan or something? That or it's just nvidia drivers being weird), the issue has reproduced on all four, on both AMD and Intel graphics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backend: glesIssues with GLES or WebGLtype: bugSomething isn't working

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions