Runs a function with a timeout. The provided closure is invoked on a thread. If the thread completes normally within the provided `duration`, its result is returned. If the thread panics within the provided `duration`, the panic is propagated to the thread calling `timeout`. Otherwise, a timeout error is returned. Note that if the invoked function does not complete in the timeout, it is not kill
(duration: Duration, f: F)
| 63 | /// not killed; it is left to wind down normally. Therefore this function is |
| 64 | /// only appropriate in tests, where the resource leak doesn't matter. |
| 65 | pub fn timeout<F, T>(duration: Duration, f: F) -> Result<T, anyhow::Error> |
| 66 | where |
| 67 | F: FnOnce() -> Result<T, anyhow::Error> + Send + 'static, |
| 68 | T: Send + 'static, |
| 69 | { |
| 70 | // Use the drop of `tx` to indicate that the thread is finished. This |
| 71 | // ensures that `tx` is dropped even if `f` panics. No actual value is ever |
| 72 | // sent on `tx`. |
| 73 | let (tx, rx) = mpsc::channel(); |
| 74 | let thread = thread::spawn(|| { |
| 75 | let _tx = tx; |
| 76 | f() |
| 77 | }); |
| 78 | match rx.recv_timeout(duration) { |
| 79 | Ok(()) => unreachable!(), |
| 80 | Err(RecvTimeoutError::Disconnected) => thread.join().unwrap(), |
| 81 | Err(RecvTimeoutError::Timeout) => bail!("thread timed out"), |
| 82 | } |
| 83 | } |
no test coverage detected