diff options
author | Glenn Watson <gw@intuitionlibrary.com> | 2015-01-29 09:58:57 +1000 |
---|---|---|
committer | Glenn Watson <gw@intuitionlibrary.com> | 2015-01-30 07:11:55 +1000 |
commit | 1b73aeaa2427318b28fc42ba47dd871136f2f0d8 (patch) | |
tree | 6fb7bf7f08b3bd39ee25176e1cb160f5de8cc5e8 | |
parent | 5611a3251391755dc943b17d9b3610710ecf2e3a (diff) | |
download | glutin-1b73aeaa2427318b28fc42ba47dd871136f2f0d8.tar.gz glutin-1b73aeaa2427318b28fc42ba47dd871136f2f0d8.zip |
On some X11 driver implementations, calling XCloseDisplay from a different thread
causes memory corruption, resulting in a crash. Change window proxy to be a weak
reference so that the XCloseDisplay is always called from the main window.
-rw-r--r-- | src/x11/window/mod.rs | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs index efdc759..d412ce0 100644 --- a/src/x11/window/mod.rs +++ b/src/x11/window/mod.rs @@ -7,7 +7,7 @@ use std::cell::Cell; use std::sync::atomic::AtomicBool; use std::collections::RingBuf; use super::ffi; -use std::sync::{Arc, Once, ONCE_INIT}; +use std::sync::{Arc, Once, ONCE_INIT, Weak}; use std::sync::{StaticMutex, MUTEX_INIT}; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; @@ -36,7 +36,7 @@ fn ensure_thread_init() { fn with_c_str<F, T>(s: &str, f: F) -> T where F: FnOnce(*const libc::c_char) -> T { use std::ffi::CString; let c_str = CString::from_slice(s.as_bytes()); - f(c_str.as_slice_with_nul().as_ptr()) + f(c_str.as_slice_with_nul().as_ptr()) } struct XWindow { @@ -50,6 +50,9 @@ struct XWindow { im: ffi::XIM, } +unsafe impl Send for XWindow {} +unsafe impl Sync for XWindow {} + unsafe impl Send for Window {} unsafe impl Sync for Window {} @@ -74,25 +77,30 @@ impl Drop for XWindow { #[derive(Clone)] pub struct WindowProxy { - x: Arc<XWindow>, + x: Weak<XWindow>, } impl WindowProxy { pub fn wakeup_event_loop(&self) { - let mut xev = ffi::XClientMessageEvent { - type_: ffi::ClientMessage, - window: self.x.window, - format: 32, - message_type: 0, - serial: 0, - send_event: 0, - display: self.x.display, - l: [0, 0, 0, 0, 0], - }; + match self.x.upgrade() { + Some(x) => { + let mut xev = ffi::XClientMessageEvent { + type_: ffi::ClientMessage, + window: x.window, + format: 32, + message_type: 0, + serial: 0, + send_event: 0, + display: x.display, + l: [0, 0, 0, 0, 0], + }; - unsafe { - ffi::XSendEvent(self.x.display, self.x.window, 0, 0, mem::transmute(&mut xev)); - ffi::XFlush(self.x.display); + unsafe { + ffi::XSendEvent(x.display, x.window, 0, 0, mem::transmute(&mut xev)); + ffi::XFlush(x.display); + } + } + None => {} } } } @@ -488,7 +496,7 @@ impl Window { pub fn create_window_proxy(&self) -> WindowProxy { WindowProxy { - x: self.x.clone() + x: self.x.downgrade() } } |