From bb25964307a87064cb2600f00dbeece0f0f78785 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 9 Aug 2021 04:21:42 +0800 Subject: [PATCH] safe exit --- Cargo.lock | 19 ++++++-- Cargo.toml | 2 +- src/ipc.rs | 1 + src/server.rs | 2 +- src/server/input_service.rs | 93 +++++++++++++++++++++++++------------ 5 files changed, 82 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a72527f73..1b2566c33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -915,6 +915,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "err-derive" version = "0.2.4" @@ -978,9 +991,9 @@ dependencies = [ [[package]] name = "flexi_logger" -version = "0.16.3" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291b6ce7b3ed2dda82efa6aee4c6bdb55fd11bc88b06c55b01851e94b96e5322" +checksum = "33ab94b6ac8eb69f1496a6993f26f785b5fd6d99b7416023eb2a6175c0b242b1" dependencies = [ "atty", "chrono", @@ -1377,7 +1390,7 @@ dependencies = [ "confy", "directories-next", "dirs-next", - "env_logger 0.8.4", + "env_logger 0.9.0", "filetime", "futures", "futures-util", diff --git a/Cargo.toml b/Cargo.toml index 7b0971f54..798dd2f13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ sha2 = "0.9" repng = "0.2" libc = "0.2" parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" } -flexi_logger = "0.16" +flexi_logger = "0.17" runas = "0.2" magnum-opus = { git = "https://github.com/open-trade/magnum-opus" } dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true } diff --git a/src/ipc.rs b/src/ipc.rs index 25dc36d3c..694f53732 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -171,6 +171,7 @@ async fn handle(data: Data, stream: &mut Connection) { } Data::Close => { log::info!("Receive close message"); + crate::server::input_service::fix_key_down_timeout_at_exit(); std::process::exit(0); } Data::OnlineStatus(_) => { diff --git a/src/server.rs b/src/server.rs index eceb4a875..541d88f29 100644 --- a/src/server.rs +++ b/src/server.rs @@ -272,7 +272,7 @@ pub async fn start_server(is_server: bool, _tray: bool) { std::process::exit(-1); } }); - input_service::fix_key_down_timeout(); + input_service::fix_key_down_timeout_loop(); crate::RendezvousMediator::start_all().await; } else { match crate::ipc::connect(1000, "").await { diff --git a/src/server/input_service.rs b/src/server/input_service.rs index 449f1da3e..68513a0a4 100644 --- a/src/server/input_service.rs +++ b/src/server/input_service.rs @@ -159,6 +159,7 @@ fn run_cursor(sp: MouseCursorService, state: &mut StateCursor) -> ResultType<()> lazy_static::lazy_static! { static ref ENIGO: Arc> = Arc::new(Mutex::new(Enigo::new())); static ref KEYS_DOWN: Arc>> = Default::default(); + static ref EXITING: Arc> = Default::default(); } // mac key input must be run in main thread, otherwise crash on >= osx 10.15 @@ -212,42 +213,66 @@ pub fn handle_mouse(evt: &MouseEvent, conn: i32) { handle_mouse_(evt, conn); } -pub fn fix_key_down_timeout() { +pub fn fix_key_down_timeout_loop() { std::thread::spawn(move || loop { std::thread::sleep(std::time::Duration::from_millis(300)); - if KEYS_DOWN.lock().unwrap().is_empty() { - continue; - } - let cloned = (*KEYS_DOWN.lock().unwrap()).clone(); - log::debug!("{} keys in key down timeout map", cloned.len()); - for (key, value) in cloned.into_iter() { - if value.elapsed().as_millis() >= 3_000 { - KEYS_DOWN.lock().unwrap().remove(&key); - let key = if key < KEY_CHAR_START { - if let Some(key) = KEY_MAP.get(&key) { - Some(*key) - } else { - None - } + fix_key_down_timeout(false); + }); + // atexit is called before exit + unsafe { libc::atexit(fix_key_down_timeout_at_exit) }; + unsafe { + libc::signal(libc::SIGINT, fix_key_down_timeout_at_signal as _); + } +} + +pub extern "C" fn fix_key_down_timeout_at_exit() { + let mut exiting = EXITING.lock().unwrap(); + if *exiting { + return; + } + *exiting = true; + fix_key_down_timeout(true); + log::info!("fix_key_down_timeout_at_exit"); +} + +extern "C" fn fix_key_down_timeout_at_signal(_: libc::c_int) { + fix_key_down_timeout_at_exit(); + std::process::exit(0); // will call atexit on posix, but not on Windows +} + +fn fix_key_down_timeout(force: bool) { + if KEYS_DOWN.lock().unwrap().is_empty() { + return; + } + let cloned = (*KEYS_DOWN.lock().unwrap()).clone(); + log::debug!("{} keys in key down timeout map", cloned.len()); + for (key, value) in cloned.into_iter() { + if force || value.elapsed().as_millis() >= 3_000 { + KEYS_DOWN.lock().unwrap().remove(&key); + let key = if key < KEY_CHAR_START { + if let Some(key) = KEY_MAP.get(&key) { + Some(*key) } else { - Some(Key::Layout(((key - KEY_CHAR_START) as u8) as _)) - }; - if let Some(key) = key { - let func = move || { - let mut en = ENIGO.lock().unwrap(); - if en.get_key_state(key) { - en.key_up(key); - log::debug!("Fixed {:?} timeout", key); - } - }; - #[cfg(target_os = "macos")] - QUEUE.exec_async(func); - #[cfg(not(target_os = "macos"))] - func(); + None } + } else { + Some(Key::Layout(((key - KEY_CHAR_START) as u8) as _)) + }; + if let Some(key) = key { + let func = move || { + let mut en = ENIGO.lock().unwrap(); + if en.get_key_state(key) { + en.key_up(key); + log::debug!("Fixed {:?} timeout", key); + } + }; + #[cfg(target_os = "macos")] + QUEUE.exec_async(func); + #[cfg(not(target_os = "macos"))] + func(); } } - }); + } } // e.g. current state of ctrl is down, but ctrl not in modifier, we should change ctrl to up, to make modifier state sync between remote and local @@ -292,6 +317,10 @@ fn fix_modifiers(modifiers: &[ProtobufEnumOrUnknown], en: &mut Enigo } fn handle_mouse_(evt: &MouseEvent, conn: i32) { + let exiting = EXITING.lock().unwrap(); + if *exiting { + return; + } #[cfg(windows)] crate::platform::windows::try_change_desktop(); let buttons = evt.mask >> 3; @@ -496,6 +525,10 @@ pub fn handle_key(evt: &KeyEvent) { } fn handle_key_(evt: &KeyEvent) { + let exiting = EXITING.lock().unwrap(); + if *exiting { + return; + } #[cfg(windows)] crate::platform::windows::try_change_desktop(); let mut en = ENIGO.lock().unwrap();