gardesk/ers / f74dc26

Browse files

fix ers shutdown and event safety

Authored by espadonne
SHA
f74dc26c71048621ac011c21dadddc0a98c95edb
Parents
bedab97
Tree
423c8c2

3 changed files

StatusFile+-
M src/events.rs 9 11
M src/main.rs 46 49
M src/skylight.rs 2 1
src/events.rsmodified
@@ -1,6 +1,8 @@
11
 //! SLS event registration and dispatch.
22
 
33
 use crate::skylight::*;
4
+use std::sync::OnceLock;
5
+use std::sync::atomic::{AtomicI32, Ordering};
46
 use std::sync::mpsc;
57
 
68
 pub const EVENT_WINDOW_CLOSE: u32 = 804;
@@ -27,21 +29,17 @@ pub enum Event {
2729
     FrontChange,
2830
 }
2931
 
30
-static mut TX: Option<mpsc::Sender<Event>> = None;
31
-static mut OWN_PID: i32 = 0;
32
+static TX: OnceLock<mpsc::Sender<Event>> = OnceLock::new();
33
+static OWN_PID: AtomicI32 = AtomicI32::new(0);
3234
 
3335
 pub fn init(tx: mpsc::Sender<Event>, own_pid: i32) {
34
-    unsafe {
35
-        TX = Some(tx);
36
-        OWN_PID = own_pid;
37
-    }
36
+    let _ = TX.set(tx);
37
+    OWN_PID.store(own_pid, Ordering::Relaxed);
3838
 }
3939
 
4040
 fn send(event: Event) {
41
-    unsafe {
42
-        if let Some(ref tx) = TX {
43
-            let _ = tx.send(event);
44
-        }
41
+    if let Some(tx) = TX.get() {
42
+        let _ = tx.send(event);
4543
     }
4644
 }
4745
 
@@ -51,7 +49,7 @@ fn is_own_window(cid: CGSConnectionID, wid: u32) -> bool {
5149
         SLSGetWindowOwner(cid, wid, &mut wid_cid);
5250
         let mut pid: i32 = 0;
5351
         SLSConnectionGetPID(wid_cid, &mut pid);
54
-        pid == OWN_PID
52
+        pid == OWN_PID.load(Ordering::Relaxed)
5553
     }
5654
 }
5755
 
src/main.rsmodified
@@ -12,6 +12,8 @@ use std::sync::atomic::{AtomicBool, Ordering};
1212
 use std::sync::mpsc;
1313
 use tracing::debug;
1414
 
15
+static SIGNAL_STOP_REQUESTED: AtomicBool = AtomicBool::new(false);
16
+
1517
 /// Per-overlay state: the connection it was created on + its wid.
1618
 struct Overlay {
1719
     cid: CGSConnectionID,
@@ -37,6 +39,14 @@ fn is_same_window_surface(a: CGRect, b: CGRect) -> bool {
3739
     smaller > 0.0 && intersection_area(a, b) / smaller >= 0.9
3840
 }
3941
 
42
+fn cf_string_from_static(name: &std::ffi::CStr) -> CFStringRef {
43
+    unsafe { CFStringCreateWithCString(ptr::null(), name.as_ptr().cast(), kCFStringEncodingUTF8) }
44
+}
45
+
46
+unsafe extern "C" fn handle_sigint(_: libc::c_int) {
47
+    SIGNAL_STOP_REQUESTED.store(true, Ordering::Relaxed);
48
+}
49
+
4050
 /// Tracks overlays for target windows.
4151
 struct BorderMap {
4252
     overlays: HashMap<u32, Overlay>,
@@ -360,21 +370,9 @@ fn get_front_window(own_pid: i32) -> u32 {
360370
         }
361371
 
362372
         let count = CFArrayGetCount(list);
363
-        let wid_key = CFStringCreateWithCString(
364
-            ptr::null(),
365
-            b"kCGWindowNumber\0".as_ptr(),
366
-            kCFStringEncodingUTF8,
367
-        );
368
-        let pid_key = CFStringCreateWithCString(
369
-            ptr::null(),
370
-            b"kCGWindowOwnerPID\0".as_ptr(),
371
-            kCFStringEncodingUTF8,
372
-        );
373
-        let layer_key = CFStringCreateWithCString(
374
-            ptr::null(),
375
-            b"kCGWindowLayer\0".as_ptr(),
376
-            kCFStringEncodingUTF8,
377
-        );
373
+        let wid_key = cf_string_from_static(c"kCGWindowNumber");
374
+        let pid_key = cf_string_from_static(c"kCGWindowOwnerPID");
375
+        let layer_key = cf_string_from_static(c"kCGWindowLayer");
378376
 
379377
         let mut front_wid: u32 = 0;
380378
         let mut front_bounds = CGRect::default();
@@ -584,17 +582,34 @@ fn main() {
584582
 
585583
     debug!("{} overlays tracked", borders.overlays.len());
586584
 
587
-    // SIGINT flag — background thread checks this to clean up
585
+    SIGNAL_STOP_REQUESTED.store(false, Ordering::Relaxed);
586
+
587
+    // Background watcher translates the signal-safe atomic into a normal
588
+    // CoreFoundation shutdown request on a Rust thread.
588589
     let running = Arc::new(AtomicBool::new(true));
590
+    let signal_watcher = std::thread::spawn(|| {
591
+        use std::time::Duration;
592
+
593
+        while !SIGNAL_STOP_REQUESTED.load(Ordering::Relaxed) {
594
+            std::thread::sleep(Duration::from_millis(10));
595
+        }
596
+
597
+        unsafe {
598
+            let run_loop = CFRunLoopGetMain();
599
+            CFRunLoopStop(run_loop);
600
+            CFRunLoopWakeUp(run_loop);
601
+        }
602
+    });
603
+
589604
     unsafe {
590
-        libc::signal(libc::SIGINT, {
591
-            unsafe extern "C" fn handler(_: libc::c_int) {
592
-                unsafe {
593
-                    CFRunLoopStop(CFRunLoopGetMain());
594
-                }
595
-            }
596
-            handler as *const () as libc::sighandler_t
597
-        });
605
+        libc::signal(
606
+            libc::SIGINT,
607
+            handle_sigint as *const () as libc::sighandler_t,
608
+        );
609
+        libc::signal(
610
+            libc::SIGTERM,
611
+            handle_sigint as *const () as libc::sighandler_t,
612
+        );
598613
     }
599614
 
600615
     // Process events on background thread with coalescing
@@ -767,6 +782,8 @@ fn main() {
767782
 
768783
     // SIGINT received — signal background thread to stop and wait
769784
     running.store(false, Ordering::Relaxed);
785
+    SIGNAL_STOP_REQUESTED.store(true, Ordering::Relaxed);
786
+    let _ = signal_watcher.join();
770787
     let _ = handle.join();
771788
 }
772789
 
@@ -820,21 +837,9 @@ fn discover_windows(_cid: CGSConnectionID, own_pid: i32) -> Vec<u32> {
820837
         }
821838
 
822839
         let count = CFArrayGetCount(list);
823
-        let wid_key = CFStringCreateWithCString(
824
-            ptr::null(),
825
-            b"kCGWindowNumber\0".as_ptr(),
826
-            kCFStringEncodingUTF8,
827
-        );
828
-        let pid_key = CFStringCreateWithCString(
829
-            ptr::null(),
830
-            b"kCGWindowOwnerPID\0".as_ptr(),
831
-            kCFStringEncodingUTF8,
832
-        );
833
-        let layer_key = CFStringCreateWithCString(
834
-            ptr::null(),
835
-            b"kCGWindowLayer\0".as_ptr(),
836
-            kCFStringEncodingUTF8,
837
-        );
840
+        let wid_key = cf_string_from_static(c"kCGWindowNumber");
841
+        let pid_key = cf_string_from_static(c"kCGWindowOwnerPID");
842
+        let layer_key = cf_string_from_static(c"kCGWindowLayer");
838843
 
839844
         let mut wids = Vec::new();
840845
         for i in 0..count {
@@ -987,16 +992,8 @@ fn list_windows() {
987992
             return;
988993
         }
989994
         let count = CFArrayGetCount(list);
990
-        let wid_key = CFStringCreateWithCString(
991
-            ptr::null(),
992
-            b"kCGWindowNumber\0".as_ptr(),
993
-            kCFStringEncodingUTF8,
994
-        );
995
-        let layer_key = CFStringCreateWithCString(
996
-            ptr::null(),
997
-            b"kCGWindowLayer\0".as_ptr(),
998
-            kCFStringEncodingUTF8,
999
-        );
995
+        let wid_key = cf_string_from_static(c"kCGWindowNumber");
996
+        let layer_key = cf_string_from_static(c"kCGWindowLayer");
1000997
 
1001998
         eprintln!(
1002999
             "{:>6}  {:>8}  {:>8}  {:>6}  {:>6}",
src/skylight.rsmodified
@@ -411,6 +411,7 @@ unsafe extern "C" {
411411
     pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
412412
     pub fn CFRunLoopRun();
413413
     pub fn CFRunLoopStop(rl: CFRunLoopRef);
414
+    pub fn CFRunLoopWakeUp(rl: CFRunLoopRef);
414415
 
415416
     pub static kCFAllocatorDefault: CFAllocatorRef;
416417
     pub static kCFTypeDictionaryKeyCallBacks: c_void;
@@ -449,7 +450,7 @@ pub unsafe fn cfarray_of_cfnumbers(
449450
             std::ptr::null(),
450451
             temp.as_ptr() as *const CFTypeRef,
451452
             count as i64,
452
-            &kCFTypeArrayCallBacks as *const _ as *const c_void,
453
+            &kCFTypeArrayCallBacks as *const _,
453454
         );
454455
         for n in &temp {
455456
             CFRelease(*n);