diff options
Diffstat (limited to 'src/libstd/sync/mpsc/sync.rs')
| -rw-r--r-- | src/libstd/sync/mpsc/sync.rs | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 9985daaba8f..1d16e002a2b 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -36,6 +36,8 @@ pub use self::Failure::*; use self::Blocker::*; +use core::intrinsics::abort; +use core::isize; use core::mem; use core::ptr; @@ -45,6 +47,8 @@ use sync::mpsc::select::StartResult::{self, Installed, Abort}; use sync::{Mutex, MutexGuard}; use time::Instant; +const MAX_REFCOUNT: usize = (isize::MAX) as usize; + pub struct Packet<T> { /// Only field outside of the mutex. Just done for kicks, but mainly because /// the other shared channel already had the code implemented @@ -350,7 +354,14 @@ impl<T> Packet<T> { // Prepares this shared packet for a channel clone, essentially just bumping // a refcount. pub fn clone_chan(&self) { - self.channels.fetch_add(1, Ordering::SeqCst); + let old_count = self.channels.fetch_add(1, Ordering::SeqCst); + + // See comments on Arc::clone() on why we do this (for `mem::forget`). + if old_count > MAX_REFCOUNT { + unsafe { + abort(); + } + } } pub fn drop_chan(&self) { |
