summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-08-27 22:05:29 +0200
committerLinus Färnstrand <linus@mullvad.net>2017-08-27 22:05:29 +0200
commita3efb3088d49cb30b7979d59cafe31f54319a95d (patch)
treec9fdfcaf5be4a862cd3109bfdb2ece85a2c2d196
parent19785be0c0d8c3e142c5288b669ed3a234f30e50 (diff)
downloadmullvadvpn-a3efb3088d49cb30b7979d59cafe31f54319a95d.tar.xz
mullvadvpn-a3efb3088d49cb30b7979d59cafe31f54319a95d.zip
Implement nice_kill in trait on Handle (polling)
-rw-r--r--talpid-core/src/process/unix.rs51
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)
}