diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2017-08-27 22:05:29 +0200 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2017-08-27 22:05:29 +0200 |
| commit | a3efb3088d49cb30b7979d59cafe31f54319a95d (patch) | |
| tree | c9fdfcaf5be4a862cd3109bfdb2ece85a2c2d196 | |
| parent | 19785be0c0d8c3e142c5288b669ed3a234f30e50 (diff) | |
| download | mullvadvpn-a3efb3088d49cb30b7979d59cafe31f54319a95d.tar.xz mullvadvpn-a3efb3088d49cb30b7979d59cafe31f54319a95d.zip | |
Implement nice_kill in trait on Handle (polling)
| -rw-r--r-- | talpid-core/src/process/unix.rs | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/talpid-core/src/process/unix.rs b/talpid-core/src/process/unix.rs index 64599a6930..189945257d 100644 --- a/talpid-core/src/process/unix.rs +++ b/talpid-core/src/process/unix.rs @@ -4,30 +4,43 @@ use duct; use duct::unix::HandleExt; use std::io; -use std::sync::{Arc, mpsc}; use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; -/// 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)?; +static POLL_INTERVAL_MS: u64 = 50; - 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() +/// Extra methods for terminating `duct::Handle` instances. +pub trait HandleKillExt { + /// 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. + fn nice_kill(&self, timeout: Duration) -> io::Result<()>; +} + +impl HandleKillExt for duct::Handle { + fn nice_kill(&self, timeout: Duration) -> io::Result<()> { + trace!("Sending SIGTERM to child process"); + self.send_signal(libc::SIGTERM)?; + + if wait_timeout(self, timeout)? { + debug!("Child process exited from SIGTERM"); + Ok(()) + } else { + debug!("Child process did not exit from SIGTERM, sending SIGKILL"); + self.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) +/// the timeout. +fn wait_timeout(handle: &duct::Handle, timeout: Duration) -> io::Result<bool> { + let timer = Instant::now(); + while timer.elapsed() < timeout { + match handle.try_wait() { + Ok(None) => thread::sleep(Duration::from_millis(POLL_INTERVAL_MS)), + Ok(Some(_)) => return Ok(true), + Err(e) => return Err(e), + } + } + Ok(false) } |
