about summary refs log tree commit diff
path: root/src/libstd/sync/mpsc/sync.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/sync/mpsc/sync.rs')
-rw-r--r--src/libstd/sync/mpsc/sync.rs13
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) {