Auto merge of #36104 - KiChjang:issue-35847, r=brson
Fix illegal instruction caused by overflow in channel cloning Fixes #35847. r? @alexcrichton
This commit is contained in:
commit
49e9bfdbf2
2 changed files with 24 additions and 4 deletions
|
@ -21,6 +21,7 @@
|
||||||
pub use self::Failure::*;
|
pub use self::Failure::*;
|
||||||
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
|
use core::intrinsics::abort;
|
||||||
use core::isize;
|
use core::isize;
|
||||||
|
|
||||||
use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
|
use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
|
||||||
|
@ -34,6 +35,7 @@ use time::Instant;
|
||||||
|
|
||||||
const DISCONNECTED: isize = isize::MIN;
|
const DISCONNECTED: isize = isize::MIN;
|
||||||
const FUDGE: isize = 1024;
|
const FUDGE: isize = 1024;
|
||||||
|
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
const MAX_STEALS: isize = 5;
|
const MAX_STEALS: isize = 5;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
|
@ -46,7 +48,7 @@ pub struct Packet<T> {
|
||||||
to_wake: AtomicUsize, // SignalToken for wake up
|
to_wake: AtomicUsize, // SignalToken for wake up
|
||||||
|
|
||||||
// The number of channels which are currently using this packet.
|
// The number of channels which are currently using this packet.
|
||||||
channels: AtomicIsize,
|
channels: AtomicUsize,
|
||||||
|
|
||||||
// See the discussion in Port::drop and the channel send methods for what
|
// See the discussion in Port::drop and the channel send methods for what
|
||||||
// these are used for
|
// these are used for
|
||||||
|
@ -72,7 +74,7 @@ impl<T> Packet<T> {
|
||||||
cnt: AtomicIsize::new(0),
|
cnt: AtomicIsize::new(0),
|
||||||
steals: 0,
|
steals: 0,
|
||||||
to_wake: AtomicUsize::new(0),
|
to_wake: AtomicUsize::new(0),
|
||||||
channels: AtomicIsize::new(2),
|
channels: AtomicUsize::new(2),
|
||||||
port_dropped: AtomicBool::new(false),
|
port_dropped: AtomicBool::new(false),
|
||||||
sender_drain: AtomicIsize::new(0),
|
sender_drain: AtomicIsize::new(0),
|
||||||
select_lock: Mutex::new(()),
|
select_lock: Mutex::new(()),
|
||||||
|
@ -340,7 +342,14 @@ impl<T> Packet<T> {
|
||||||
// Prepares this shared packet for a channel clone, essentially just bumping
|
// Prepares this shared packet for a channel clone, essentially just bumping
|
||||||
// a refcount.
|
// a refcount.
|
||||||
pub fn clone_chan(&mut self) {
|
pub fn clone_chan(&mut 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrement the reference count on a channel. This is called whenever a
|
// Decrement the reference count on a channel. This is called whenever a
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
pub use self::Failure::*;
|
pub use self::Failure::*;
|
||||||
use self::Blocker::*;
|
use self::Blocker::*;
|
||||||
|
|
||||||
|
use core::intrinsics::abort;
|
||||||
|
use core::isize;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
@ -45,6 +47,8 @@ use sync::mpsc::select::StartResult::{self, Installed, Abort};
|
||||||
use sync::{Mutex, MutexGuard};
|
use sync::{Mutex, MutexGuard};
|
||||||
use time::Instant;
|
use time::Instant;
|
||||||
|
|
||||||
|
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||||
|
|
||||||
pub struct Packet<T> {
|
pub struct Packet<T> {
|
||||||
/// Only field outside of the mutex. Just done for kicks, but mainly because
|
/// Only field outside of the mutex. Just done for kicks, but mainly because
|
||||||
/// the other shared channel already had the code implemented
|
/// 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
|
// Prepares this shared packet for a channel clone, essentially just bumping
|
||||||
// a refcount.
|
// a refcount.
|
||||||
pub fn clone_chan(&self) {
|
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) {
|
pub fn drop_chan(&self) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue