diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-06-13 11:45:13 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-06-13 13:42:11 +0200 |
| commit | 351dcdc456833a3d93f842e381a3a0d9ad886dd4 (patch) | |
| tree | 5e8609df33a9222ba0ee2c3431c616126ce67902 | |
| parent | 734ca1551d08b6cadc4331916b8d53e681a379a4 (diff) | |
| download | mullvadvpn-351dcdc456833a3d93f842e381a3a0d9ad886dd4.tar.xz mullvadvpn-351dcdc456833a3d93f842e381a3a0d9ad886dd4.zip | |
Add nice_kill method for graceful child exit
| -rw-r--r-- | talpid_core/Cargo.toml | 5 | ||||
| -rw-r--r-- | talpid_core/src/process/mod.rs | 4 | ||||
| -rw-r--r-- | talpid_core/src/process/unix.rs | 33 |
3 files changed, 41 insertions, 1 deletions
diff --git a/talpid_core/Cargo.toml b/talpid_core/Cargo.toml index 6fd7222f27..4b3afa4d80 100644 --- a/talpid_core/Cargo.toml +++ b/talpid_core/Cargo.toml @@ -5,12 +5,15 @@ authors = ["Linus Färnstrand <linus@mullvad.net>", "Erik Larkö <erik@mullvad.n description = "Core backend functionality of the Mullvad VPN client" [dependencies] -duct = "0.8" +duct = "0.9.1" error-chain = "0.10" log = "0.3" jsonrpc-core = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-handle" } jsonrpc-macros = { git = "https://github.com/faern/jsonrpc", branch = "ws-close-handle" } +[target.'cfg(unix)'.dependencies] +libc = "0.2.20" + [dependencies.talpid_ipc] path = "../talpid_ipc" diff --git a/talpid_core/src/process/mod.rs b/talpid_core/src/process/mod.rs index 6ae568907b..88bdc12ea4 100644 --- a/talpid_core/src/process/mod.rs +++ b/talpid_core/src/process/mod.rs @@ -1,2 +1,6 @@ /// A module for all OpenVPN related process management. pub mod openvpn; + +/// Unix specific process management features. +#[cfg(unix)] +pub mod unix; diff --git a/talpid_core/src/process/unix.rs b/talpid_core/src/process/unix.rs new file mode 100644 index 0000000000..64599a6930 --- /dev/null +++ b/talpid_core/src/process/unix.rs @@ -0,0 +1,33 @@ +extern crate libc; + +use duct; +use duct::unix::HandleExt; + +use std::io; +use std::sync::{Arc, mpsc}; +use std::thread; +use std::time::Duration; + +/// Kills a process by first sending it the `SIGTERM` signal and then wait up to `timeout`. If the +/// process has not died after the timeout has expired it is killed. +pub fn nice_kill(handle: Arc<duct::Handle>, timeout: Duration) -> io::Result<()> { + trace!("Sending SIGTERM to child process"); + handle.send_signal(libc::SIGTERM)?; + + if wait_timeout(handle.clone(), timeout) { + debug!("Child process exited from SIGTERM"); + Ok(()) + } else { + debug!("Child process did not exit from SIGTERM, sending SIGKILL"); + handle.kill() + } +} + +/// Wait for a process to die for a maximum of `timeout`. Returns true if the process died within +/// the timeout. Warning, if the process does not exit in the given time, this function will leave +/// a thread running until it does exit. +fn wait_timeout(handle: Arc<duct::Handle>, timeout: Duration) -> bool { + let (stop, stopped) = mpsc::channel(); + thread::spawn(move || { let _ = stop.send(handle.wait().is_ok()); }); + stopped.recv_timeout(timeout).unwrap_or(false) +} |
