aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Watson <gw@intuitionlibrary.com>2015-01-29 09:58:57 +1000
committerGlenn Watson <gw@intuitionlibrary.com>2015-01-30 07:11:55 +1000
commit1b73aeaa2427318b28fc42ba47dd871136f2f0d8 (patch)
tree6fb7bf7f08b3bd39ee25176e1cb160f5de8cc5e8
parent5611a3251391755dc943b17d9b3610710ecf2e3a (diff)
downloadglutin-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.rs42
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()
}
}