ctrlc/platform/unix/
mod.rs1use crate::error::Error as CtrlcError;
11
12#[cfg(not(target_vendor = "apple"))]
13#[allow(static_mut_refs)] mod implementation {
15 static mut SEMAPHORE: nix::libc::sem_t = unsafe { std::mem::zeroed() };
16 const SEM_THREAD_SHARED: nix::libc::c_int = 0;
17
18 pub unsafe fn sem_init() {
19 nix::libc::sem_init(&mut SEMAPHORE as *mut _, SEM_THREAD_SHARED, 0);
20 }
21
22 pub unsafe fn sem_post() {
23 let _ = nix::libc::sem_post(&mut SEMAPHORE as *mut _);
25 }
26
27 pub unsafe fn sem_wait_forever() {
28 while nix::libc::sem_wait(&mut SEMAPHORE as *mut _) == -1 {}
30 }
31}
32
33#[cfg(target_vendor = "apple")]
34mod implementation {
35 static mut SEMAPHORE: dispatch::ffi::dispatch_semaphore_t = std::ptr::null_mut();
36
37 pub unsafe fn sem_init() {
38 SEMAPHORE = dispatch::ffi::dispatch_semaphore_create(0);
39 }
40
41 pub unsafe fn sem_post() {
42 dispatch::ffi::dispatch_semaphore_signal(SEMAPHORE);
43 }
44
45 pub unsafe fn sem_wait_forever() {
46 dispatch::ffi::dispatch_semaphore_wait(SEMAPHORE, dispatch::ffi::DISPATCH_TIME_FOREVER);
47 }
48}
49
50pub type Error = nix::Error;
52
53pub type Signal = nix::sys::signal::Signal;
55
56extern "C" fn os_handler(_: nix::libc::c_int) {
57 unsafe {
58 implementation::sem_post();
59 }
60}
61
62#[inline]
71pub unsafe fn init_os_handler(overwrite: bool) -> Result<(), Error> {
72 use nix::sys::signal;
73
74 implementation::sem_init();
75
76 let handler = signal::SigHandler::Handler(os_handler);
77 #[cfg(not(target_os = "nto"))]
78 let new_action = signal::SigAction::new(
79 handler,
80 signal::SaFlags::SA_RESTART,
81 signal::SigSet::empty(),
82 );
83 #[cfg(target_os = "nto")]
85 let new_action =
86 signal::SigAction::new(handler, signal::SaFlags::empty(), signal::SigSet::empty());
87
88 let sigint_old = signal::sigaction(signal::Signal::SIGINT, &new_action)?;
89 if !overwrite && sigint_old.handler() != signal::SigHandler::SigDfl {
90 signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap();
91 return Err(nix::Error::EEXIST);
92 }
93
94 #[cfg(feature = "termination")]
95 {
96 let sigterm_old = match signal::sigaction(signal::Signal::SIGTERM, &new_action) {
97 Ok(old) => old,
98 Err(e) => {
99 signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap();
100 return Err(e);
101 }
102 };
103 if !overwrite && sigterm_old.handler() != signal::SigHandler::SigDfl {
104 signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap();
105 signal::sigaction(signal::Signal::SIGTERM, &sigterm_old).unwrap();
106 return Err(nix::Error::EEXIST);
107 }
108 let sighup_old = match signal::sigaction(signal::Signal::SIGHUP, &new_action) {
109 Ok(old) => old,
110 Err(e) => {
111 signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap();
112 signal::sigaction(signal::Signal::SIGTERM, &sigterm_old).unwrap();
113 return Err(e);
114 }
115 };
116 if !overwrite && sighup_old.handler() != signal::SigHandler::SigDfl {
117 signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap();
118 signal::sigaction(signal::Signal::SIGTERM, &sigterm_old).unwrap();
119 signal::sigaction(signal::Signal::SIGHUP, &sighup_old).unwrap();
120 return Err(nix::Error::EEXIST);
121 }
122 }
123
124 Ok(())
125}
126
127#[inline]
135pub unsafe fn block_ctrl_c() -> Result<(), CtrlcError> {
136 implementation::sem_wait_forever();
137 Ok(())
138}