Skip to content

Commit

Permalink
channel: 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 15, 2022
1 parent 0081fcc commit baedeb0
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 6 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::convert_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::convert_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::convert_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::convert_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::convert_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::convert_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 convert_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

0 comments on commit baedeb0

Please sign in to comment.