summaryrefslogtreecommitdiff
path: root/cli/lsp/parent_process_checker.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp/parent_process_checker.rs')
-rw-r--r--cli/lsp/parent_process_checker.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/cli/lsp/parent_process_checker.rs b/cli/lsp/parent_process_checker.rs
new file mode 100644
index 000000000..6c80969f4
--- /dev/null
+++ b/cli/lsp/parent_process_checker.rs
@@ -0,0 +1,70 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
+use tokio::time::sleep;
+use tokio::time::Duration;
+
+/// Starts a task that will check for the existence of the
+/// provided process id. Once that process no longer exists
+/// it will terminate the current process.
+pub fn start(parent_process_id: u32) {
+ tokio::task::spawn(async move {
+ loop {
+ sleep(Duration::from_secs(30)).await;
+
+ if !is_process_active(parent_process_id) {
+ eprintln!("Parent process lost. Exiting.");
+ std::process::exit(1);
+ }
+ }
+ });
+}
+
+#[cfg(unix)]
+fn is_process_active(process_id: u32) -> bool {
+ unsafe {
+ // signal of 0 checks for the existence of the process id
+ libc::kill(process_id as i32, 0) == 0
+ }
+}
+
+#[cfg(windows)]
+fn is_process_active(process_id: u32) -> bool {
+ use winapi::shared::minwindef::DWORD;
+ use winapi::shared::minwindef::FALSE;
+ use winapi::shared::ntdef::NULL;
+ use winapi::shared::winerror::WAIT_TIMEOUT;
+ use winapi::um::handleapi::CloseHandle;
+ use winapi::um::processthreadsapi::OpenProcess;
+ use winapi::um::synchapi::WaitForSingleObject;
+ use winapi::um::winnt::SYNCHRONIZE;
+
+ unsafe {
+ let process = OpenProcess(SYNCHRONIZE, FALSE, process_id as DWORD);
+ let result = if process == NULL {
+ false
+ } else {
+ WaitForSingleObject(process, 0) == WAIT_TIMEOUT
+ };
+ CloseHandle(process);
+ result
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::is_process_active;
+ use std::process::Command;
+ use test_util::deno_exe_path;
+
+ #[test]
+ fn process_active() {
+ // launch a long running process
+ let mut child = Command::new(deno_exe_path()).arg("lsp").spawn().unwrap();
+
+ let pid = child.id();
+ assert_eq!(is_process_active(pid), true);
+ child.kill().unwrap();
+ child.wait().unwrap();
+ assert_eq!(is_process_active(pid), false);
+ }
+}