Skip to content

Commit

Permalink
Merge #591
Browse files Browse the repository at this point in the history
591: Run sanitizers on CI r=jeehoonkang a=taiki-e

This adds AddressSanitizer/MemorySanitizer/ThreadSanitizer tests to CI.

See #589 (tsan: data race in deque), #644 (tsan: data race in atomic), and #614 (asan: memory leak in skiplist) for issues reported by sanitizers.

Closes #154
Closes #589
Closes #644 

Refs: 
- https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/sanitizer.html
- https://github.com/google/sanitizers/wiki

Co-authored-by: Taiki Endo <te316e89@gmail.com>
  • Loading branch information
bors[bot] and taiki-e committed Feb 15, 2021
2 parents e85d8f4 + b05c62d commit b71b944
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 20 deletions.
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Expand Up @@ -108,12 +108,23 @@ jobs:
- name: clippy
run: ./ci/clippy.sh

# Run sanitizers.
san:
name: san
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update nightly && rustup default nightly
- name: Run sanitizers
run: ./ci/san.sh

# Run loom tests.
loom:
name: loom
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable && rustup default stable
- name: loom
Expand Down Expand Up @@ -145,6 +156,7 @@ jobs:
- dependencies
- rustfmt
- clippy
- san
- loom
- docs
runs-on: ubuntu-latest
Expand Down
40 changes: 40 additions & 0 deletions ci/san.sh
@@ -0,0 +1,40 @@
#!/bin/bash

cd "$(dirname "$0")"/..
set -ex

if [[ "$OSTYPE" != "linux"* ]]; then
exit 0
fi

rustup component add rust-src

# Run address sanitizer
# https://github.com/crossbeam-rs/crossbeam/issues/614
export ASAN_OPTIONS="detect_leaks=0"
cargo clean
# TODO: Once `cfg(sanitize = "..")` is stable, replace
# `cfg(crossbeam_sanitize)` with `cfg(sanitize = "..")` and remove
# `--cfg crossbeam_sanitize`.
RUSTFLAGS="-Dwarnings -Zsanitizer=address --cfg crossbeam_sanitize" \
cargo test --all --release --target x86_64-unknown-linux-gnu --tests --exclude benchmarks -- --test-threads=1

cargo clean
RUSTFLAGS="-Dwarnings -Zsanitizer=address --cfg crossbeam_sanitize" \
cargo run \
--release \
--target x86_64-unknown-linux-gnu \
--features nightly \
--example sanitize \
--manifest-path crossbeam-epoch/Cargo.toml

# Run memory sanitizer
cargo clean
RUSTFLAGS="-Dwarnings -Zsanitizer=memory --cfg crossbeam_sanitize" \
cargo test -Zbuild-std --all --release --target x86_64-unknown-linux-gnu --tests --exclude benchmarks -- --test-threads=1

# Run thread sanitizer
export TSAN_OPTIONS="suppressions=$(pwd)/ci/tsan"
cargo clean
RUSTFLAGS="-Dwarnings -Zsanitizer=thread --cfg crossbeam_sanitize" \
cargo test -Zbuild-std --all --release --target x86_64-unknown-linux-gnu --tests --exclude benchmarks -- --test-threads=1
20 changes: 1 addition & 19 deletions ci/test.sh
Expand Up @@ -8,7 +8,7 @@ export RUSTFLAGS="-D warnings"
if [[ -n "$TARGET" ]]; then
# If TARGET is specified, use cross for testing.
cargo install cross
cross test --all --target "$TARGET" --exclude benchmarks
cross test --all --target "$TARGET" --exclude benchmarks -- --test-threads=1

# For now, the non-host target only runs tests.
exit 0
Expand All @@ -25,22 +25,4 @@ if [[ "$RUST_VERSION" == "nightly"* ]]; then
# Benchmarks are only checked on nightly because depending on unstable features.
cargo check --all --benches
cargo check --bins --manifest-path crossbeam-channel/benchmarks/Cargo.toml

# Run address sanitizer on crossbeam-epoch
# Note: this will be significantly rewritten by https://github.com/crossbeam-rs/crossbeam/pull/591.
if [[ "$OSTYPE" == "linux"* ]]; then
cargo clean

# TODO: Once `cfg(sanitize = "..")` is stable, replace
# `cfg(crossbeam_sanitize)` with `cfg(sanitize = "..")` and remove
# `--cfg crossbeam_sanitize`.
ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0" \
RUSTFLAGS="-Z sanitizer=address --cfg crossbeam_sanitize" \
cargo run \
--release \
--target x86_64-unknown-linux-gnu \
--features nightly \
--example sanitize \
--manifest-path crossbeam-epoch/Cargo.toml
fi
fi
13 changes: 13 additions & 0 deletions ci/tsan
@@ -0,0 +1,13 @@
# TSAN suppressions file for crossbeam

# The epoch-based GC uses fences.
race:crossbeam_epoch

# Push and steal operations in crossbeam-deque may cause data races, but such
# data races are safe. If a data race happens, the value read by `steal` is
# forgotten and the steal operation is then retried.
race:crossbeam_deque*push
race:crossbeam_deque*steal

# Non-lock-free AtomicCell uses SeqLock which uses fences.
race:crossbeam_utils::atomic::atomic_cell::AtomicCell<T>::compare_exchange
2 changes: 2 additions & 0 deletions crossbeam-channel/tests/tick.rs
Expand Up @@ -127,6 +127,7 @@ fn recv() {
assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
}

#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow
#[test]
fn recv_timeout() {
let start = Instant::now();
Expand Down Expand Up @@ -251,6 +252,7 @@ fn select() {
assert_eq!(hits.load(Ordering::SeqCst), 8);
}

#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow
#[test]
fn ready() {
const THREADS: usize = 4;
Expand Down
1 change: 1 addition & 0 deletions crossbeam-epoch/src/collector.rs
Expand Up @@ -199,6 +199,7 @@ mod tests {
.unwrap();
}

#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to `cfg(crossbeam_sanitize)` reduce `internal::MAX_OBJECTS`
#[test]
fn incremental() {
const COUNT: usize = 100_000;
Expand Down
1 change: 1 addition & 0 deletions crossbeam-epoch/src/internal.rs
Expand Up @@ -375,6 +375,7 @@ pub(crate) struct Local {

// Make sure `Local` is less than or equal to 2048 bytes.
// https://github.com/crossbeam-rs/crossbeam/issues/551
#[cfg(not(crossbeam_sanitize))] // `crossbeam_sanitize` reduces the size of `Local`
#[test]
fn local_size() {
assert!(
Expand Down

0 comments on commit b71b944

Please sign in to comment.