diff options
| author | bors <bors@rust-lang.org> | 2019-01-02 02:03:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-01-02 02:03:15 +0000 |
| commit | 96530344ef951c79e07cad69cf65eddb876b0e2d (patch) | |
| tree | e8e9ecad3e45da009e2cd410b3756810064f3b65 /src/libstd/sync | |
| parent | 443ae75eaf86e59da21b75e2e72b7b1dcf2c90e5 (diff) | |
| parent | 496f547af604f5430ab6fbb3ce78ef0ea79a6ae8 (diff) | |
| download | rust-96530344ef951c79e07cad69cf65eddb876b0e2d.tar.gz rust-96530344ef951c79e07cad69cf65eddb876b0e2d.zip | |
Auto merge of #56827 - faern:eliminate-recv-timeout-panic, r=KodrAus
Eliminate Receiver::recv_timeout panic Fixes #54552. This panic is because `recv_timeout` uses `Instant::now() + timeout` internally. This possible panic is not mentioned in the documentation for this method. Very recently we merged (still unstable) support for checked addition (#56490) of `Instant + Duration`, so it's now finally possible to add these together without risking a panic.
Diffstat (limited to 'src/libstd/sync')
| -rw-r--r-- | src/libstd/sync/mpsc/mod.rs | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index ecdf7e5668c..446c164965d 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1311,12 +1311,13 @@ impl<T> Receiver<T> { // Do an optimistic try_recv to avoid the performance impact of // Instant::now() in the full-channel case. match self.try_recv() { - Ok(result) - => Ok(result), - Err(TryRecvError::Disconnected) - => Err(RecvTimeoutError::Disconnected), - Err(TryRecvError::Empty) - => self.recv_deadline(Instant::now() + timeout) + Ok(result) => Ok(result), + Err(TryRecvError::Disconnected) => Err(RecvTimeoutError::Disconnected), + Err(TryRecvError::Empty) => match Instant::now().checked_add(timeout) { + Some(deadline) => self.recv_deadline(deadline), + // So far in the future that it's practically the same as waiting indefinitely. + None => self.recv().map_err(RecvTimeoutError::from), + }, } } @@ -2302,6 +2303,17 @@ mod tests { } #[test] + fn very_long_recv_timeout_wont_panic() { + let (tx, rx) = channel::<()>(); + let join_handle = thread::spawn(move || { + rx.recv_timeout(Duration::from_secs(u64::max_value())) + }); + thread::sleep(Duration::from_secs(1)); + assert!(tx.send(()).is_ok()); + assert_eq!(join_handle.join().unwrap(), Ok(())); + } + + #[test] fn recv_a_lot() { // Regression test that we don't run out of stack in scheduler context let (tx, rx) = channel(); |
