Skip to content

Commit 65e7ecf

Browse files
authored
Merge branch 'master' into port-fix-discard-all-message
2 parents bbff85d + c5ac785 commit 65e7ecf

File tree

18 files changed

+140
-93
lines changed

18 files changed

+140
-93
lines changed

.github/dependabot.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,18 @@ updates:
77
commit-message:
88
prefix: ''
99
labels: []
10+
groups:
11+
cargo:
12+
patterns:
13+
- '*'
14+
- package-ecosystem: github-actions
15+
directory: /
16+
schedule:
17+
interval: weekly
18+
commit-message:
19+
prefix: ''
20+
labels: []
21+
groups:
22+
github-actions:
23+
patterns:
24+
- '*'

.github/workflows/ci.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ jobs:
4040
matrix:
4141
# aarch64/x86_64 macOS and aarch64 Linux are tested on Cirrus CI
4242
include:
43-
- rust: '1.61'
43+
- rust: '1.63'
4444
os: ubuntu-latest
45-
- rust: '1.61'
45+
- rust: '1.63'
4646
os: windows-latest
4747
- rust: stable
4848
os: ubuntu-latest
@@ -135,7 +135,7 @@ jobs:
135135
if ! git diff --exit-code; then
136136
git add .
137137
git commit -m "Update no_atomic.rs"
138-
echo "::set-output name=success::false"
138+
echo 'success=false' >>"${GITHUB_OUTPUT}"
139139
fi
140140
if: github.repository_owner == 'crossbeam-rs' && github.event_name == 'schedule'
141141
- uses: peter-evans/create-pull-request@v5
@@ -174,14 +174,20 @@ jobs:
174174

175175
# Run miri.
176176
miri:
177+
strategy:
178+
fail-fast: false
179+
matrix:
180+
group:
181+
- channel
182+
- others
177183
runs-on: ubuntu-latest
178184
timeout-minutes: 120 # TODO
179185
steps:
180186
- uses: taiki-e/checkout-action@v1
181187
- name: Install Rust
182188
run: rustup toolchain install nightly --component miri && rustup default nightly
183189
- name: miri
184-
run: ci/miri.sh
190+
run: ci/miri.sh ${{ matrix.group }}
185191

186192
# Run cargo-careful.
187193
careful:

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ unexpected_cfgs = { level = "warn", check-cfg = [
6969
] }
7070
unreachable_pub = "warn"
7171
# unsafe_op_in_unsafe_fn = "warn" # Set at crate-level instead since https://github.com/rust-lang/rust/pull/100081 is not available on MSRV
72+
[workspace.lints.clippy]
73+
# Suppress buggy or noisy clippy lints
74+
declare_interior_mutable_const = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/7665
75+
lint_groups_priority = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/12920

ci/miri.sh

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,46 @@ set -euxo pipefail
33
IFS=$'\n\t'
44
cd "$(dirname "$0")"/..
55

6+
group=$1
7+
68
# We need 'ts' for the per-line timing
79
sudo apt-get -y install moreutils
810
echo
911

1012
export RUSTFLAGS="${RUSTFLAGS:-} -Z randomize-layout"
1113
export RUSTDOCFLAGS="${RUSTDOCFLAGS:-} -Z randomize-layout"
14+
export MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation"
1215

13-
MIRIFLAGS="-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation" \
14-
MIRI_LEAK_CHECK='1' \
15-
cargo miri test \
16-
-p crossbeam-channel \
17-
-p crossbeam-queue \
18-
-p crossbeam-utils 2>&1 | ts -i '%.s '
19-
20-
# -Zmiri-ignore-leaks is needed because we use detached threads in tests in tests/golang.rs: https://github.com/rust-lang/miri/issues/1371
21-
MIRIFLAGS="-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation -Zmiri-ignore-leaks" \
22-
cargo miri test \
23-
-p crossbeam-channel --test golang 2>&1 | ts -i '%.s '
24-
25-
# Use Tree Borrows instead of Stacked Borrows because epoch is not compatible with Stacked Borrows: https://github.com/crossbeam-rs/crossbeam/issues/545#issuecomment-1192785003
26-
MIRIFLAGS="-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation -Zmiri-tree-borrows" \
27-
cargo miri test \
28-
-p crossbeam-epoch \
29-
-p crossbeam-skiplist \
30-
-p crossbeam 2>&1 | ts -i '%.s '
31-
32-
# Use Tree Borrows instead of Stacked Borrows because epoch is not compatible with Stacked Borrows: https://github.com/crossbeam-rs/crossbeam/issues/545#issuecomment-1192785003
33-
# -Zmiri-compare-exchange-weak-failure-rate=0.0 is needed because some sequential tests (e.g.,
34-
# doctest of Stealer::steal) incorrectly assume that sequential weak CAS will never fail.
35-
# -Zmiri-preemption-rate=0 is needed because this code technically has UB and Miri catches that.
36-
MIRIFLAGS="-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation -Zmiri-tree-borrows -Zmiri-compare-exchange-weak-failure-rate=0.0 -Zmiri-preemption-rate=0" \
37-
cargo miri test \
38-
-p crossbeam-deque 2>&1 | ts -i '%.s '
16+
case "${group}" in
17+
channel)
18+
MIRI_LEAK_CHECK='1' \
19+
cargo miri test \
20+
-p crossbeam-channel 2>&1 | ts -i '%.s '
21+
# -Zmiri-ignore-leaks is needed because we use detached threads in tests in tests/golang.rs: https://github.com/rust-lang/miri/issues/1371
22+
MIRIFLAGS="${MIRIFLAGS} -Zmiri-ignore-leaks" \
23+
cargo miri test \
24+
-p crossbeam-channel --test golang 2>&1 | ts -i '%.s '
25+
;;
26+
others)
27+
cargo miri test \
28+
-p crossbeam-queue \
29+
-p crossbeam-utils 2>&1 | ts -i '%.s '
30+
# Use Tree Borrows instead of Stacked Borrows because epoch is not compatible with Stacked Borrows: https://github.com/crossbeam-rs/crossbeam/issues/545#issuecomment-1192785003
31+
MIRIFLAGS="${MIRIFLAGS} -Zmiri-tree-borrows" \
32+
cargo miri test \
33+
-p crossbeam-epoch \
34+
-p crossbeam-skiplist \
35+
-p crossbeam 2>&1 | ts -i '%.s '
36+
# Use Tree Borrows instead of Stacked Borrows because epoch is not compatible with Stacked Borrows: https://github.com/crossbeam-rs/crossbeam/issues/545#issuecomment-1192785003
37+
# -Zmiri-compare-exchange-weak-failure-rate=0.0 is needed because some sequential tests (e.g.,
38+
# doctest of Stealer::steal) incorrectly assume that sequential weak CAS will never fail.
39+
# -Zmiri-preemption-rate=0 is needed because this code technically has UB and Miri catches that.
40+
MIRIFLAGS="${MIRIFLAGS} -Zmiri-tree-borrows -Zmiri-compare-exchange-weak-failure-rate=0.0 -Zmiri-preemption-rate=0" \
41+
cargo miri test \
42+
-p crossbeam-deque 2>&1 | ts -i '%.s '
43+
;;
44+
*)
45+
echo "unknown crate group '${group}'"
46+
exit 1
47+
;;
48+
esac

ci/no_atomic.sh

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,45 +8,24 @@ cd "$(dirname "$0")"/..
88
# Usage:
99
# ./ci/no_atomic.sh
1010

11-
file="no_atomic.rs"
11+
file=no_atomic.rs
1212

13-
no_atomic=()
14-
for target_spec in $(RUSTC_BOOTSTRAP=1 rustc +stable -Z unstable-options --print all-target-specs-json | jq -c '. | to_entries | .[]'); do
15-
target=$(jq <<<"${target_spec}" -r '.key')
16-
target_spec=$(jq <<<"${target_spec}" -c '.value')
17-
res=$(jq <<<"${target_spec}" -r 'select(."atomic-cas" == false)')
18-
[[ -z "${res}" ]] || no_atomic_cas+=("${target}")
19-
max_atomic_width=$(jq <<<"${target_spec}" -r '."max-atomic-width"')
20-
min_atomic_width=$(jq <<<"${target_spec}" -r '."min-atomic-width"')
21-
case "${max_atomic_width}" in
22-
# `"max-atomic-width" == 0` means that atomic is not supported at all.
23-
# We do not have a cfg for targets with {8,16}-bit atomic only, so
24-
# for now we treat them the same as targets that do not support atomic.
25-
0) no_atomic+=("${target}") ;;
26-
# It is not clear exactly what `"max-atomic-width" == null` means, but they
27-
# actually seem to have the same max-atomic-width as the target-pointer-width.
28-
# The targets currently included in this group are "mipsel-sony-psp",
29-
# "thumbv4t-none-eabi", "thumbv6m-none-eabi", all of which are
30-
# `"target-pointer-width" == "32"`, so assuming them `"max-atomic-width" == 32`
31-
# for now.
32-
null | 8 | 16 | 32 | 64 | 128) ;;
33-
*) exit 1 ;;
34-
esac
35-
case "${min_atomic_width}" in
36-
8 | null) ;;
37-
*) no_atomic+=("${target}") ;;
38-
esac
39-
done
13+
# `"max-atomic-width" == 0` means that atomic is not supported at all.
14+
# We do not have a cfg for targets with {8,16}-bit atomic only, so
15+
# for now we treat them the same as targets that do not support atomic.
16+
# It is not clear exactly what `"max-atomic-width" == null` means, but they
17+
# actually seem to have the same max-atomic-width as the target-pointer-width.
18+
# The targets currently included in this group are "mipsel-sony-psp",
19+
# "thumbv4t-none-eabi", "thumbv6m-none-eabi", all of which are
20+
# `"target-pointer-width" == "32"`, so assuming them `"max-atomic-width" == 32`
21+
# for now.
22+
no_atomic=$(RUSTC_BOOTSTRAP=1 rustc +stable -Z unstable-options --print all-target-specs-json | jq -r '. | to_entries[] | select((.value."max-atomic-width" == 0) or (.value."min-atomic-width" and .value."min-atomic-width" != 8)) | " \"" + .key + "\","')
4023

4124
cat >"${file}" <<EOF
42-
// This file is @generated by $(basename "$0").
25+
// This file is @generated by ${0##*/}.
4326
// It is not intended for manual editing.
4427
4528
const NO_ATOMIC: &[&str] = &[
46-
EOF
47-
for target in "${no_atomic[@]}"; do
48-
echo " \"${target}\"," >>"${file}"
49-
done
50-
cat >>"${file}" <<EOF
29+
${no_atomic}
5130
];
5231
EOF

crossbeam-channel/src/flavors/list.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Unbounded channel implemented as a linked list.
22
3+
use std::alloc::{alloc_zeroed, handle_alloc_error, Layout};
34
use std::boxed::Box;
45
use std::cell::UnsafeCell;
56
use std::marker::PhantomData;
@@ -50,11 +51,6 @@ struct Slot<T> {
5051
}
5152

5253
impl<T> Slot<T> {
53-
const UNINIT: Self = Self {
54-
msg: UnsafeCell::new(MaybeUninit::uninit()),
55-
state: AtomicUsize::new(0),
56-
};
57-
5854
/// Waits until a message is written into the slot.
5955
fn wait_write(&self) {
6056
let backoff = Backoff::new();
@@ -77,11 +73,26 @@ struct Block<T> {
7773

7874
impl<T> Block<T> {
7975
/// Creates an empty block.
80-
fn new() -> Self {
81-
Self {
82-
next: AtomicPtr::new(ptr::null_mut()),
83-
slots: [Slot::UNINIT; BLOCK_CAP],
76+
fn new() -> Box<Self> {
77+
let layout = Layout::new::<Self>();
78+
assert!(
79+
layout.size() != 0,
80+
"Block should never be zero-sized, as it has an AtomicPtr field"
81+
);
82+
// SAFETY: layout is not zero-sized
83+
let ptr = unsafe { alloc_zeroed(layout) };
84+
// Handle allocation failure
85+
if ptr.is_null() {
86+
handle_alloc_error(layout)
8487
}
88+
// SAFETY: This is safe because:
89+
// [1] `Block::next` (AtomicPtr) may be safely zero initialized.
90+
// [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
91+
// [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it
92+
// holds a MaybeUninit.
93+
// [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
94+
// TODO: unsafe { Box::new_zeroed().assume_init() }
95+
unsafe { Box::from_raw(ptr.cast()) }
8596
}
8697

8798
/// Waits until the next pointer is set.
@@ -223,13 +234,13 @@ impl<T> Channel<T> {
223234
// If we're going to have to install the next block, allocate it in advance in order to
224235
// make the wait for other threads as short as possible.
225236
if offset + 1 == BLOCK_CAP && next_block.is_none() {
226-
next_block = Some(Box::new(Block::<T>::new()));
237+
next_block = Some(Block::<T>::new());
227238
}
228239

229240
// If this is the first message to be sent into the channel, we need to allocate the
230241
// first block and install it.
231242
if block.is_null() {
232-
let new = Box::into_raw(Box::new(Block::<T>::new()));
243+
let new = Box::into_raw(Block::<T>::new());
233244

234245
if self
235246
.tail

crossbeam-channel/src/select_macro.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ macro_rules! crossbeam_channel_internal {
687687
const _LEN: usize = $crate::crossbeam_channel_internal!(@count ($($cases)*));
688688
let _handle: &dyn $crate::internal::SelectHandle = &$crate::never::<()>();
689689

690-
#[allow(unused_mut)]
690+
#[allow(unused_mut, clippy::zero_repeat_side_effects)]
691691
let mut _sel = [(_handle, 0, ::std::ptr::null()); _LEN];
692692

693693
$crate::crossbeam_channel_internal!(

crossbeam-channel/tests/list.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,3 +580,18 @@ fn channel_through_channel() {
580580
})
581581
.unwrap();
582582
}
583+
584+
// If `Block` is created on the stack, the array of slots will multiply this `BigStruct` and
585+
// probably overflow the thread stack. It's now directly created on the heap to avoid this.
586+
#[test]
587+
fn stack_overflow() {
588+
const N: usize = 32_768;
589+
struct BigStruct {
590+
_data: [u8; N],
591+
}
592+
593+
let (sender, receiver) = unbounded::<BigStruct>();
594+
sender.send(BigStruct { _data: [0u8; N] }).unwrap();
595+
596+
for _data in receiver.try_iter() {}
597+
}

crossbeam-channel/tests/select_macro.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ fn fairness1() {
858858
assert!(hits.iter().all(|x| *x >= COUNT / hits.len() / 2));
859859
}
860860

861+
#[cfg_attr(crossbeam_sanitize, ignore)] // TODO: flaky: https://github.com/crossbeam-rs/crossbeam/issues/1094
861862
#[test]
862863
fn fairness2() {
863864
#[cfg(miri)]

crossbeam-deque/src/deque.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::fmt;
55
use std::marker::PhantomData;
66
use std::mem::{self, MaybeUninit};
77
use std::ptr;
8-
use std::slice;
98
use std::sync::atomic::{self, AtomicIsize, AtomicPtr, AtomicUsize, Ordering};
109
use std::sync::Arc;
1110

@@ -52,7 +51,7 @@ impl<T> Buffer<T> {
5251
/// Deallocates the buffer.
5352
unsafe fn dealloc(self) {
5453
drop(unsafe {
55-
Box::from_raw(slice::from_raw_parts_mut(
54+
Box::from_raw(ptr::slice_from_raw_parts_mut(
5655
self.ptr.cast::<MaybeUninit<T>>(),
5756
self.cap,
5857
))

0 commit comments

Comments
 (0)