Skip to content

Commit

Permalink
Do not panic on very large timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Mar 12, 2022
1 parent 0081fcc commit 070cd26
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 7 deletions.
5 changes: 3 additions & 2 deletions crossbeam-channel/src/channel.rs
Expand Up @@ -14,6 +14,7 @@ use crate::err::{
};
use crate::flavors;
use crate::select::{Operation, SelectHandle, Token};
use crate::utils;

/// Creates a channel of unbounded capacity.
///
Expand Down Expand Up @@ -471,7 +472,7 @@ impl<T> Sender<T> {
/// );
/// ```
pub fn send_timeout(&self, msg: T, timeout: Duration) -> Result<(), SendTimeoutError<T>> {
self.send_deadline(msg, Instant::now() + timeout)
self.send_deadline(msg, utils::timeout_to_deadline(timeout))
}

/// Waits for a message to be sent into the channel, but only until a given deadline.
Expand Down Expand Up @@ -861,7 +862,7 @@ impl<T> Receiver<T> {
/// );
/// ```
pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
self.recv_deadline(Instant::now() + timeout)
self.recv_deadline(utils::timeout_to_deadline(timeout))
}

/// Waits for a message to be received from the channel, but only before a given deadline.
Expand Down
2 changes: 1 addition & 1 deletion crossbeam-channel/src/flavors/at.rs
Expand Up @@ -35,7 +35,7 @@ impl Channel {
/// Creates a channel that delivers a message after a certain duration of time.
#[inline]
pub(crate) fn new_timeout(dur: Duration) -> Self {
Self::new_deadline(Instant::now() + dur)
Self::new_deadline(utils::timeout_to_deadline(dur))
}

/// Attempts to receive a message without blocking.
Expand Down
3 changes: 2 additions & 1 deletion crossbeam-channel/src/flavors/tick.rs
Expand Up @@ -10,6 +10,7 @@ use crossbeam_utils::atomic::AtomicCell;
use crate::context::Context;
use crate::err::{RecvTimeoutError, TryRecvError};
use crate::select::{Operation, SelectHandle, Token};
use crate::utils;

/// Result of a receive operation.
pub(crate) type TickToken = Option<Instant>;
Expand All @@ -28,7 +29,7 @@ impl Channel {
#[inline]
pub(crate) fn new(dur: Duration) -> Self {
Channel {
delivery_time: AtomicCell::new(Instant::now() + dur),
delivery_time: AtomicCell::new(utils::timeout_to_deadline(dur)),
duration: dur,
}
}
Expand Down
4 changes: 2 additions & 2 deletions crossbeam-channel/src/select.rs
Expand Up @@ -487,7 +487,7 @@ pub fn select_timeout<'a>(
handles: &mut [(&'a dyn SelectHandle, usize, *const u8)],
timeout: Duration,
) -> Result<SelectedOperation<'a>, SelectTimeoutError> {
select_deadline(handles, Instant::now() + timeout)
select_deadline(handles, utils::timeout_to_deadline(timeout))
}

/// Blocks until a given deadline, or until one of the operations becomes ready and selects it.
Expand Down Expand Up @@ -1043,7 +1043,7 @@ impl<'a> Select<'a> {
/// }
/// ```
pub fn ready_timeout(&mut self, timeout: Duration) -> Result<usize, ReadyTimeoutError> {
self.ready_deadline(Instant::now() + timeout)
self.ready_deadline(utils::timeout_to_deadline(timeout))
}

/// Blocks until a given deadline, or until one of the operations becomes ready.
Expand Down
8 changes: 8 additions & 0 deletions crossbeam-channel/src/utils.rs
Expand Up @@ -61,6 +61,14 @@ pub(crate) fn sleep_until(deadline: Option<Instant>) {
}
}

// https://github.com/crossbeam-rs/crossbeam/issues/795
pub(crate) fn timeout_to_deadline(timeout: Duration) -> Instant {
match Instant::now().checked_add(timeout) {
Some(deadline) => deadline,
None => Instant::now() + Duration::from_secs(86400 * 365 * 30),
}
}

/// A simple spinlock.
pub(crate) struct Spinlock<T> {
flag: AtomicBool,
Expand Down
7 changes: 6 additions & 1 deletion crossbeam-utils/src/sync/parker.rs
Expand Up @@ -121,7 +121,12 @@ impl Parker {
/// p.park_timeout(Duration::from_millis(500));
/// ```
pub fn park_timeout(&self, timeout: Duration) {
self.park_deadline(Instant::now() + timeout)
// https://github.com/crossbeam-rs/crossbeam/issues/795
let deadline = match Instant::now().checked_add(timeout) {
Some(deadline) => deadline,
None => Instant::now() + Duration::from_secs(86400 * 365 * 30),
};
self.park_deadline(deadline)
}

/// Blocks the current thread until the token is made available, or until a certain deadline.
Expand Down

0 comments on commit 070cd26

Please sign in to comment.