Skip to content

Commit

Permalink
X11: Fix super fun race conditions (#554)
Browse files Browse the repository at this point in the history
* X11: Fix super fun race conditions

* Fix build on rustc<1.26
  • Loading branch information
francesca64 authored Jun 7, 2018
1 parent 8891cfd commit 262490d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both.
- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched.
- On macOS, windows without decorations can once again be resized.
- Fixed race conditions when creating an `EventsLoop` on X11, most commonly manifesting as "[xcb] Unknown sequence number while processing queue".

# Version 0.15.0 (2018-05-22)

Expand Down
60 changes: 33 additions & 27 deletions src/platform/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub x11_window_type: x11::util::WindowType,
}

lazy_static!(
pub static ref X11_BACKEND: Result<Arc<XConnection>, XNotSupported> = {
thread_local!(
pub static X11_BACKEND: Result<Arc<XConnection>, XNotSupported> = {
XConnection::new(Some(x_error_callback)).map(Arc::new)
};
);
Expand Down Expand Up @@ -342,27 +342,29 @@ unsafe extern "C" fn x_error_callback(
display: *mut x11::ffi::Display,
event: *mut x11::ffi::XErrorEvent,
) -> c_int {
if let Ok(ref xconn) = *X11_BACKEND {
let mut buf: [c_char; 1024] = mem::uninitialized();
(xconn.xlib.XGetErrorText)(
display,
(*event).error_code as c_int,
buf.as_mut_ptr(),
buf.len() as c_int,
);
let description = CStr::from_ptr(buf.as_ptr()).to_string_lossy();

let error = XError {
description: description.into_owned(),
error_code: (*event).error_code,
request_code: (*event).request_code,
minor_code: (*event).minor_code,
};

eprintln!("[winit X11 error] {:#?}", error);

*xconn.latest_error.lock() = Some(error);
}
X11_BACKEND.with(|result| {
if let &Ok(ref xconn) = result {
let mut buf: [c_char; 1024] = mem::uninitialized();
(xconn.xlib.XGetErrorText)(
display,
(*event).error_code as c_int,
buf.as_mut_ptr(),
buf.len() as c_int,
);
let description = CStr::from_ptr(buf.as_ptr()).to_string_lossy();

let error = XError {
description: description.into_owned(),
error_code: (*event).error_code,
request_code: (*event).request_code,
minor_code: (*event).minor_code,
};

eprintln!("[winit X11 error] {:#?}", error);

*xconn.latest_error.lock() = Some(error);
}
});
// Fun fact: this return value is completely ignored.
0
}
Expand Down Expand Up @@ -424,10 +426,14 @@ r#"Failed to initialize any backend!
}

pub fn new_x11() -> Result<EventsLoop, XNotSupported> {
match *X11_BACKEND {
Ok(ref x) => Ok(EventsLoop::X(x11::EventsLoop::new(x.clone()))),
Err(ref err) => Err(err.clone()),
}
X11_BACKEND.with(|result| {
result
.as_ref()
.map(Arc::clone)
.map(x11::EventsLoop::new)
.map(EventsLoop::X)
.map_err(|err| err.clone())
})
}

#[inline]
Expand Down
8 changes: 8 additions & 0 deletions src/platform/linux/x11/ime/input_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@ use std::sync::Arc;
use std::os::raw::c_char;
use std::ffi::{CStr, CString, IntoStringError};

use parking_lot::Mutex;

use super::{ffi, util, XConnection, XError};

lazy_static! {
static ref GLOBAL_LOCK: Mutex<()> = Default::default();
}

unsafe fn open_im(
xconn: &Arc<XConnection>,
locale_modifiers: &CStr,
) -> Option<ffi::XIM> {
let _lock = GLOBAL_LOCK.lock();

// XSetLocaleModifiers returns...
// * The current locale modifiers if it's given a NULL pointer.
// * The new locale modifiers if we succeeded in setting them.
Expand Down

0 comments on commit 262490d

Please sign in to comment.