From 018f8a027d47cce44aa90c97ae4baa069ebccc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 14 Dec 2018 19:24:19 +0100 Subject: [PATCH 1/2] Use checked_add for adding time in recv_timeout --- src/libstd/sync/mpsc/mod.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 059ced4f56efd..99424c8a92f7e 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1321,12 +1321,13 @@ impl Receiver { // 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), + }, } } @@ -2311,6 +2312,17 @@ mod tests { assert_eq!(recv_count, stress); } + #[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 From 496f547af604f5430ab6fbb3ce78ef0ea79a6ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 14 Dec 2018 20:07:04 +0100 Subject: [PATCH 2/2] Add documentation about panicking Add impls --- src/libstd/time.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 63cede79e4843..5bac4f50f1f40 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -230,6 +230,12 @@ impl Instant { impl Add for Instant { type Output = Instant; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add fn add(self, other: Duration) -> Instant { self.checked_add(other) .expect("overflow when adding duration to instant") @@ -397,6 +403,12 @@ impl SystemTime { impl Add for SystemTime { type Output = SystemTime; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add fn add(self, dur: Duration) -> SystemTime { self.checked_add(dur) .expect("overflow when adding duration to instant")