From 8524e87319401b0dfb30b23d02cfcd9da4244f18 Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Wed, 19 Jun 2024 14:36:57 +0200 Subject: [PATCH] linux/x11: Do panic when unmapping/destroying of X11 window fails (#13262) We saw this panic come up: ``` called `Result::unwrap()` on an `Err` value: IoError(Custom { kind: Other, error: UnknownError }) core::panicking::panic_fmt core::result::unwrap_failed ::drop core::ptr::drop_in_place core::ptr::drop_in_place gpui::app::AppContext::shutdown gpui::app::AppContext::new::{{closure}} gpui::platform::linux::platform::::run gpui::app::App::run zed::main std::sys_common::backtrace::__rust_begin_short_backtrace std::rt::lang_start::{{closure}} std::rt::lang_start_internal main __libc_start_call_main __libc_start_main_impl _start ``` I'm not sure where exactly that error comes from, except from the X11 stuff. So let's be defensive and log error and only then tear down everything. I _think_ that if the error is repeatable that means we won't close the window but instead just log errors, but I do think that's better than panicking right now. Release Notes: - N/A --- crates/gpui/src/platform/linux/x11/window.rs | 46 ++++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index 5e48faaad1..c7c8cf0708 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -1,3 +1,5 @@ +use anyhow::Context; + use crate::{ platform::blade::{BladeRenderer, BladeSurfaceConfig}, px, size, AnyWindowHandle, Bounds, DevicePixels, ForegroundExecutor, Modifiers, Pixels, @@ -8,7 +10,7 @@ use crate::{ use blade_graphics as gpu; use raw_window_handle as rwh; -use util::ResultExt; +use util::{maybe, ResultExt}; use x11rb::{ connection::Connection, protocol::{ @@ -422,26 +424,32 @@ impl Drop for X11Window { let mut state = self.0.state.borrow_mut(); state.renderer.destroy(); - self.0.xcb_connection.unmap_window(self.0.x_window).unwrap(); - self.0 - .xcb_connection - .destroy_window(self.0.x_window) - .unwrap(); - self.0.xcb_connection.flush().unwrap(); + let destroy_x_window = maybe!({ + self.0.xcb_connection.unmap_window(self.0.x_window)?; + self.0.xcb_connection.destroy_window(self.0.x_window)?; + self.0.xcb_connection.flush()?; - // Mark window as destroyed so that we can filter out when X11 events - // for it still come in. - state.destroyed = true; + anyhow::Ok(()) + }) + .context("unmapping and destroying X11 window") + .log_err(); + + if destroy_x_window.is_some() { + // Mark window as destroyed so that we can filter out when X11 events + // for it still come in. + state.destroyed = true; + + let this_ptr = self.0.clone(); + let client_ptr = state.client.clone(); + state + .executor + .spawn(async move { + this_ptr.close(); + client_ptr.drop_window(this_ptr.x_window); + }) + .detach(); + } - let this_ptr = self.0.clone(); - let client_ptr = state.client.clone(); - state - .executor - .spawn(async move { - this_ptr.close(); - client_ptr.drop_window(this_ptr.x_window); - }) - .detach(); drop(state); } }