21
21
pub use self :: Failure :: * ;
22
22
23
23
use core:: cmp;
24
+ use core:: intrinsics:: abort;
24
25
use core:: isize;
25
26
26
27
use sync:: atomic:: { AtomicUsize , AtomicIsize , AtomicBool , Ordering } ;
@@ -34,6 +35,7 @@ use time::Instant;
34
35
35
36
const DISCONNECTED : isize = isize:: MIN ;
36
37
const FUDGE : isize = 1024 ;
38
+ const MAX_REFCOUNT : usize = ( isize:: MAX ) as usize ;
37
39
#[ cfg( test) ]
38
40
const MAX_STEALS : isize = 5 ;
39
41
#[ cfg( not( test) ) ]
@@ -46,7 +48,7 @@ pub struct Packet<T> {
46
48
to_wake : AtomicUsize , // SignalToken for wake up
47
49
48
50
// The number of channels which are currently using this packet.
49
- channels : AtomicIsize ,
51
+ channels : AtomicUsize ,
50
52
51
53
// See the discussion in Port::drop and the channel send methods for what
52
54
// these are used for
@@ -72,7 +74,7 @@ impl<T> Packet<T> {
72
74
cnt : AtomicIsize :: new ( 0 ) ,
73
75
steals : 0 ,
74
76
to_wake : AtomicUsize :: new ( 0 ) ,
75
- channels : AtomicIsize :: new ( 2 ) ,
77
+ channels : AtomicUsize :: new ( 2 ) ,
76
78
port_dropped : AtomicBool :: new ( false ) ,
77
79
sender_drain : AtomicIsize :: new ( 0 ) ,
78
80
select_lock : Mutex :: new ( ( ) ) ,
@@ -340,7 +342,14 @@ impl<T> Packet<T> {
340
342
// Prepares this shared packet for a channel clone, essentially just bumping
341
343
// a refcount.
342
344
pub fn clone_chan ( & mut self ) {
343
- self . channels . fetch_add ( 1 , Ordering :: SeqCst ) ;
345
+ let old_count = self . channels . fetch_add ( 1 , Ordering :: SeqCst ) ;
346
+
347
+ // See comments on Arc::clone() on why we do this (for `mem::forget`).
348
+ if old_count > MAX_REFCOUNT {
349
+ unsafe {
350
+ abort ( ) ;
351
+ }
352
+ }
344
353
}
345
354
346
355
// Decrement the reference count on a channel. This is called whenever a
0 commit comments