Skip to content

add a test for the TLS memory leak #3501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,18 @@ function run_tests_minimal {
## Main Testing Logic ##

# In particular, fully cover all tier 1 targets.
# We also want to run the many-seeds tests on all tier 1 targets.
case $HOST_TARGET in
x86_64-unknown-linux-gnu)
# Host
GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests
# Extra tier 1
MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
MIRI_TEST_TARGET=x86_64-apple-darwin run_tests
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
# With reduced many-seed count to avoid spending too much time on that.
# (All OSes are run with 64 seeds at least once though via the macOS runner.)
MANY_SEEDS=16 MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests
MANY_SEEDS=16 MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
MANY_SEEDS=16 MIRI_TEST_TARGET=x86_64-apple-darwin run_tests
MANY_SEEDS=16 MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
# Extra tier 2
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests
Expand All @@ -155,13 +157,15 @@ case $HOST_TARGET in
# Host (tier 2)
GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests
# Extra tier 1
MIRI_TEST_TARGET=x86_64-pc-windows-msvc CARGO_MIRI_ENV=1 run_tests
MANY_SEEDS=64 MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
MANY_SEEDS=64 MIRI_TEST_TARGET=x86_64-pc-windows-msvc CARGO_MIRI_ENV=1 run_tests
# Extra tier 2
MIRI_TEST_TARGET=s390x-unknown-linux-gnu run_tests # big-endian architecture
;;
i686-pc-windows-msvc)
# Host
# Only smoke-test `many-seeds`; 64 runs take 15min here!
# Only smoke-test `many-seeds`; 64 runs of just the scoped-thread-leak test take 15min here!
# See <https://github.com/rust-lang/miri/issues/3509>.
GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=1 TEST_BENCH=1 run_tests
# Extra tier 1
# We really want to ensure a Linux target works on a Windows host,
Expand Down
4 changes: 3 additions & 1 deletion src/concurrency/weak_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
validate,
)?;
if global.track_outdated_loads && recency == LoadRecency::Outdated {
this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad);
this.emit_diagnostic(NonHaltingDiagnostic::WeakMemoryOutdatedLoad {
ptr: place.ptr(),
});
}

return Ok(loaded);
Expand Down
11 changes: 7 additions & 4 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ pub enum NonHaltingDiagnostic {
Int2Ptr {
details: bool,
},
WeakMemoryOutdatedLoad,
WeakMemoryOutdatedLoad {
ptr: Pointer<Option<Provenance>>,
},
}

/// Level of Miri specific diagnostics
Expand Down Expand Up @@ -583,7 +585,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
| AccessedAlloc(..)
| FreedAlloc(..)
| ProgressReport { .. }
| WeakMemoryOutdatedLoad => ("tracking was triggered".to_string(), DiagLevel::Note),
| WeakMemoryOutdatedLoad { .. } =>
("tracking was triggered".to_string(), DiagLevel::Note),
};

let msg = match &e {
Expand All @@ -610,8 +613,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
ProgressReport { .. } =>
format!("progress report: current operation being executed is here"),
Int2Ptr { .. } => format!("integer-to-pointer cast"),
WeakMemoryOutdatedLoad =>
format!("weak memory emulation: outdated value returned from load"),
WeakMemoryOutdatedLoad { ptr } =>
format!("weak memory emulation: outdated value returned from load at {ptr}"),
};

let notes = match &e {
Expand Down
26 changes: 26 additions & 0 deletions tests/many-seeds/tls-leak.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/123583>.
use std::thread;

fn with_thread_local1() {
thread_local! { static X: Box<u8> = Box::new(0); }
X.with(|_x| {})
}

fn with_thread_local2() {
thread_local! { static Y: Box<u8> = Box::new(0); }
Y.with(|_y| {})
}

fn main() {
// Here we have two threads racing on initializing the thread-local and adding it to the global
// dtor list (on targets that have such a list, i.e., targets without target_thread_local).
let t = thread::spawn(with_thread_local1);
with_thread_local1();
t.join().unwrap();

// Here we have one thread running the destructors racing with another thread initializing a
// thread-local. The second thread adds a destructor that could be picked up by the first.
let t = thread::spawn(|| { /* immediately just run destructors */ });
with_thread_local2(); // initialize thread-local
t.join().unwrap();
}
Loading