Swap out X11 error handling mutex for a RefCell
This commit is contained in:
parent
0aae938af0
commit
85b6437de8
|
@ -2,20 +2,20 @@ use std::ffi::CStr;
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use x11::xlib;
|
use x11::xlib;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::panic::AssertUnwindSafe;
|
use std::panic::AssertUnwindSafe;
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
/// Used as part of [`XerrorHandler::handle()`]. When an X11 error occurs during this function,
|
/// Used as part of [`XerrorHandler::handle()`]. When an X11 error occurs during this function,
|
||||||
/// the error gets copied to this mutex after which the program is allowed to resume. The error
|
/// the error gets copied to this RefCell after which the program is allowed to resume. The
|
||||||
/// can then be converted to a regular Rust Result value afterwards.
|
/// error can then be converted to a regular Rust Result value afterwards.
|
||||||
static CURRENT_X11_ERROR: Mutex<Option<xlib::XErrorEvent>> = Mutex::new(None);
|
static CURRENT_X11_ERROR: RefCell<Option<xlib::XErrorEvent>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper struct for safe X11 error handling
|
/// A helper struct for safe X11 error handling
|
||||||
pub struct XErrorHandler<'a> {
|
pub struct XErrorHandler<'a> {
|
||||||
display: *mut xlib::Display,
|
display: *mut xlib::Display,
|
||||||
mutex: &'a Mutex<Option<xlib::XErrorEvent>>,
|
error: &'a RefCell<Option<xlib::XErrorEvent>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> XErrorHandler<'a> {
|
impl<'a> XErrorHandler<'a> {
|
||||||
|
@ -25,7 +25,7 @@ impl<'a> XErrorHandler<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
xlib::XSync(self.display, 0);
|
xlib::XSync(self.display, 0);
|
||||||
}
|
}
|
||||||
let error = self.mutex.lock().unwrap().take();
|
let error = self.error.borrow_mut().take();
|
||||||
|
|
||||||
match error {
|
match error {
|
||||||
None => Ok(()),
|
None => Ok(()),
|
||||||
|
@ -44,20 +44,16 @@ impl<'a> XErrorHandler<'a> {
|
||||||
// SAFETY: the error pointer should be safe to copy
|
// SAFETY: the error pointer should be safe to copy
|
||||||
let err = *err;
|
let err = *err;
|
||||||
|
|
||||||
CURRENT_X11_ERROR.with(|mutex| match mutex.lock() {
|
CURRENT_X11_ERROR.with(|error| {
|
||||||
|
let mut error = error.borrow_mut();
|
||||||
|
match error.as_mut() {
|
||||||
// If multiple errors occur, keep the first one since that's likely going to be the
|
// If multiple errors occur, keep the first one since that's likely going to be the
|
||||||
// cause of the other errors
|
// cause of the other errors
|
||||||
Ok(mut current_error) if current_error.is_none() => {
|
Some(_) => 1,
|
||||||
*current_error = Some(err);
|
None => {
|
||||||
|
*error = Some(err);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
Ok(_) => 0,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!(
|
|
||||||
"[FATAL] raw-gl-context: Failed to lock for X11 Error Handler: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
1
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -67,13 +63,13 @@ impl<'a> XErrorHandler<'a> {
|
||||||
xlib::XSync(display, 0);
|
xlib::XSync(display, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CURRENT_X11_ERROR.with(|mutex| {
|
CURRENT_X11_ERROR.with(|error| {
|
||||||
// Make sure to clear any errors from the last call to this function
|
// Make sure to clear any errors from the last call to this function
|
||||||
*mutex.lock().unwrap() = None;
|
*error.borrow_mut() = None;
|
||||||
|
|
||||||
let old_handler = unsafe { xlib::XSetErrorHandler(Some(error_handler)) };
|
let old_handler = unsafe { xlib::XSetErrorHandler(Some(error_handler)) };
|
||||||
let panic_result = std::panic::catch_unwind(AssertUnwindSafe(|| {
|
let panic_result = std::panic::catch_unwind(AssertUnwindSafe(|| {
|
||||||
let mut h = XErrorHandler { display, mutex: &mutex };
|
let mut h = XErrorHandler { display, error };
|
||||||
handler(&mut h)
|
handler(&mut h)
|
||||||
}));
|
}));
|
||||||
// Whatever happened, restore old error handler
|
// Whatever happened, restore old error handler
|
||||||
|
|
Loading…
Reference in a new issue