diff --git a/Cargo.lock b/Cargo.lock index dca2a1517..9b7219706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,6 +114,7 @@ dependencies = [ "molc", "serde", "serde_json", + "windows", ] [[package]] diff --git a/crates/els/Cargo.toml b/crates/els/Cargo.toml index c7b69da20..02e45492b 100644 --- a/crates/els/Cargo.toml +++ b/crates/els/Cargo.toml @@ -30,7 +30,11 @@ molc = { version = "0.3" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.85" lsp-types = { version = "0.93.2", features = ["proposed"] } + +[target.'cfg(unix)'.dependencies] libc = "0.2" +[target.'cfg(windows)'.dependencies] +windows = { version = "0.58", features = ["Win32_System_Threading"] } [dev-dependencies] erg_proc_macros = { workspace = true } diff --git a/crates/els/diagnostics.rs b/crates/els/diagnostics.rs index 48f09cd2b..7442ba9c1 100644 --- a/crates/els/diagnostics.rs +++ b/crates/els/diagnostics.rs @@ -34,13 +34,37 @@ use crate::server::{DefaultFeatures, ELSResult, RedirectableStdout, Server}; use crate::server::{ASK_AUTO_SAVE_ID, HEALTH_CHECKER_ID}; use crate::util::{self, NormalizedUrl}; -pub fn is_parent_alive(parent_pid: i32) -> bool { +#[cfg(unix)] +pub fn is_process_alive(pid: i32) -> bool { unsafe { // sig 0: check if the process exists - let alive = libc::kill(parent_pid, 0); + let alive = libc::kill(pid, 0); alive == 0 } } +#[cfg(windows)] +pub fn is_process_alive(pid: i32) -> bool { + unsafe { + use windows::Win32::System::Threading::{ + GetExitCodeProcess, OpenProcess, PROCESS_QUERY_INFORMATION, + }; + + const STILL_ACTIVE: u32 = 0x103u32; + + let Ok(handle) = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid as u32) else { + return false; + }; + let mut code = 0; + let Ok(_) = GetExitCodeProcess(handle, &mut code) else { + return false; + }; + code == STILL_ACTIVE + } +} +#[cfg(all(not(windows), not(unix)))] +pub fn is_process_alive(_pid: i32) -> bool { + false +} #[derive(Debug)] pub enum BuildASTError { @@ -531,6 +555,9 @@ impl Server { if self.stdout_redirect.is_some() { return; } + let Some(client_pid) = self.init_params.process_id.map(|x| x as i32) else { + return; + }; let _self = self.clone(); // FIXME: close this thread when the server is restarted spawn_new_thread( @@ -554,11 +581,6 @@ impl Server { }, "start_client_health_checker_sender", ); - let parent_pid = self - .init_params - .process_id - .map(|x| x as i32) - .unwrap_or_else(|| unsafe { libc::getppid() }); spawn_new_thread( move || { loop { @@ -575,7 +597,7 @@ impl Server { // _log!(self, "Restart the server"); // send_error_info("Something went wrong, ELS has been restarted").unwrap(); // self_.restart(); - if !is_parent_alive(parent_pid) { + if !is_process_alive(client_pid) { lsp_log!("Client seems to be dead"); panic!("Client seems to be dead"); }