summaryrefslogtreecommitdiffhomepage
path: root/src/process/monitor.rs
diff options
context:
space:
mode:
authorLinus Färnstrand <linus@mullvad.net>2017-02-09 11:18:52 +0100
committerLinus Färnstrand <linus@mullvad.net>2017-02-09 11:18:52 +0100
commit82890bc9840f77973fa7c48d72d9e51004c75f40 (patch)
treedc75d9ad991d368ebe6dbd6bac591e813fe228dd /src/process/monitor.rs
parentb460c4c138ad283746e12604975d9d1235381ed4 (diff)
parent9d551d691a5b9981fb2c1d80801031889ca022a0 (diff)
downloadmullvadvpn-82890bc9840f77973fa7c48d72d9e51004c75f40.tar.xz
mullvadvpn-82890bc9840f77973fa7c48d72d9e51004c75f40.zip
Merge branch 'error-chain'
Diffstat (limited to 'src/process/monitor.rs')
-rw-r--r--src/process/monitor.rs77
1 files changed, 24 insertions, 53 deletions
diff --git a/src/process/monitor.rs b/src/process/monitor.rs
index e8d32a7973..8caac5cc79 100644
--- a/src/process/monitor.rs
+++ b/src/process/monitor.rs
@@ -1,11 +1,27 @@
-use std::error::Error;
-use std::fmt;
use std::io;
use std::process::{ChildStdout, ChildStderr};
use std::sync::{Arc, Mutex};
use std::thread;
+error_chain! {
+ errors {
+ /// The transition could not be made because the state machine was not in a state that
+ /// could transition to the desired state.
+ InvalidState {
+ description("Invalid state for desired transition")
+ }
+ /// Error representing a failure in spawning the child process
+ Spawn {
+ description("Unable to spawn child process")
+ }
+ /// Error representing a failure in sending a kill signal to the child process
+ Kill {
+ description("Unable to send kill signal to process")
+ }
+ }
+}
+
/// Trait for objects that represent child processes that `ChildMonitor` can monitor
pub trait MonitoredChild: Clone + Send + 'static {
/// Waits for the child to exit completely, returning if the child exited cleanly or not.
@@ -31,49 +47,6 @@ pub trait ChildSpawner: Send + 'static {
}
-/// Type alias for results of transitions in the `ChildMonitor` state machine.
-pub type TransitionResult<T> = Result<T, TransitionError>;
-
-/// Error type for transitions in the `ChildMonitor` state machine.
-#[derive(Debug)]
-pub enum TransitionError {
- /// The transition could not be made because the state machine was not in a state that could
- /// transition to the desired state.
- InvalidState,
-
- /// The transition failed because of an `io::Error`.
- IoError(io::Error),
-}
-
-impl From<io::Error> for TransitionError {
- fn from(error: io::Error) -> Self {
- TransitionError::IoError(error)
- }
-}
-
-impl fmt::Display for TransitionError {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.write_str(self.description())
- }
-}
-
-impl Error for TransitionError {
- fn description(&self) -> &str {
- match *self {
- TransitionError::InvalidState => "Invalid state for desired transition",
- TransitionError::IoError(..) => "Transition failed due to IO error",
- }
- }
-
- fn cause(&self) -> Option<&Error> {
- match *self {
- TransitionError::IoError(ref e) => Some(e),
- _ => None,
- }
- }
-}
-
-
enum State<C: MonitoredChild> {
Stopped,
Running(RunningState<C>),
@@ -104,14 +77,12 @@ impl<S: ChildSpawner> ChildMonitor<S> {
/// Starts the child process and begins to monitor it. `listener` will be called as soon as the
/// child process exits.
- pub fn start<L>(&mut self,
- listener: L)
- -> TransitionResult<(Option<ChildStdout>, Option<ChildStderr>)>
+ pub fn start<L>(&mut self, listener: L) -> Result<(Option<ChildStdout>, Option<ChildStderr>)>
where L: FnMut(bool) + Send + 'static
{
let mut state_lock = self.state.lock().unwrap();
if let State::Stopped = *state_lock {
- let mut child = self.spawner.spawn()?;
+ let mut child = self.spawner.spawn().chain_err(|| ErrorKind::Spawn)?;
let io = (child.stdout(), child.stderr());
let thread_handle = self.spawn_monitor(child.clone(), listener);
*state_lock = State::Running(RunningState {
@@ -120,7 +91,7 @@ impl<S: ChildSpawner> ChildMonitor<S> {
});
Ok(io)
} else {
- Err(TransitionError::InvalidState)
+ Err(ErrorKind::InvalidState.into())
}
}
@@ -139,13 +110,13 @@ impl<S: ChildSpawner> ChildMonitor<S> {
}
/// Sends a kill signal to the child process.
- pub fn stop(&self) -> TransitionResult<()> {
+ pub fn stop(&self) -> Result<()> {
let state_lock = self.state.lock().unwrap();
if let State::Running(ref running_state) = *state_lock {
- running_state.child.kill()?;
+ running_state.child.kill().chain_err(|| ErrorKind::Kill)?;
Ok(())
} else {
- Err(TransitionError::InvalidState)
+ Err(ErrorKind::InvalidState.into())
}
}
}