diff options
author | Daniel Fox Franke <dfoxfranke@gmail.com> | 2020-01-24 14:23:58 -0500 |
---|---|---|
committer | Carl Lerche <me@carllerche.com> | 2020-01-24 11:23:58 -0800 |
commit | 968c143acdde1905219880ba662cecb58c4aa82d (patch) | |
tree | cf391e06eadf1cf3e1a9f5443675b728099766e5 /tokio/src/task | |
parent | 6fbaac91e01ca32de58a07d93bfe2f23580e7a2d (diff) |
task: add methods for inspecting JoinErrors (#2051)
Adds `is_cancelled()` and `is_panic()` methods to `JoinError`, as well as
`into_panic()` and `try_into_panic()` methods which, when applicable, returns
the payload of the panic.
Diffstat (limited to 'tokio/src/task')
-rw-r--r-- | tokio/src/task/error.rs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/tokio/src/task/error.rs b/tokio/src/task/error.rs index 9a2eceae..d5f65a49 100644 --- a/tokio/src/task/error.rs +++ b/tokio/src/task/error.rs @@ -39,6 +39,95 @@ impl JoinError { repr: Repr::Panic(Mutex::new(err)), } } + + /// Returns true if the error was caused by the task being cancelled + pub fn is_cancelled(&self) -> bool { + match &self.repr { + Repr::Cancelled => true, + _ => false, + } + } + + /// Returns true if the error was caused by the task panicking + /// + /// # Examples + /// + /// ``` + /// use std::panic; + /// + /// #[tokio::main] + /// async fn main() { + /// let err = tokio::spawn(async { + /// panic!("boom"); + /// }).await.unwrap_err(); + /// + /// assert!(err.is_panic()); + /// } + /// ``` + pub fn is_panic(&self) -> bool { + match &self.repr { + Repr::Panic(_) => true, + _ => false, + } + } + + /// Consumes the join error, returning the object with which the task panicked. + /// + /// # Panics + /// + /// `into_panic()` panics if the `Error` does not represent the underlying + /// task terminating with a panic. Use `is_panic` to check the error reason + /// or `try_into_panic` for a variant that does not panic. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// #[tokio::main] + /// async fn main() { + /// let err = tokio::spawn(async { + /// panic!("boom"); + /// }).await.unwrap_err(); + /// + /// if err.is_panic() { + /// // Resume the panic on the main task + /// panic::resume_unwind(err.into_panic()); + /// } + /// } + /// ``` + pub fn into_panic(self) -> Box<dyn Any + Send + 'static> { + self.try_into_panic() + .expect("`JoinError` reason is not a panic.") + } + + /// Consumes the join error, returning the object with which the task + /// panicked if the task terminated due to a panic. Otherwise, `self` is + /// returned. + /// + /// # Examples + /// + /// ```should_panic + /// use std::panic; + /// + /// #[tokio::main] + /// async fn main() { + /// let err = tokio::spawn(async { + /// panic!("boom"); + /// }).await.unwrap_err(); + /// + /// if let Ok(reason) = err.try_into_panic() { + /// // Resume the panic on the main task + /// panic::resume_unwind(reason); + /// } + /// } + /// ``` + pub fn try_into_panic(self) -> Result<Box<dyn Any + Send + 'static>, JoinError> { + match self.repr { + Repr::Panic(p) => Ok(p.into_inner().expect("Extracting panic from mutex")), + _ => Err(self), + } + } } impl fmt::Display for JoinError { |