rust/tests/ui/sanitizer/thread.rs
Martin Nordholts e1d4f2a0c2 tests: Require run-fail ui tests to have an exit code (SIGABRT not ok)
And introduce two new directives for ui tests:
* `run-crash`
* `run-fail-or-crash`

Normally a `run-fail` ui test like tests that panic shall not be
terminated by a signal like `SIGABRT`. So begin having that as a hard
requirement.

Some of our current tests do terminate by a signal/crash however.
Introduce and use `run-crash` for those tests. Note that Windows crashes
are not handled by signals but by certain high bits set on the process
exit code. Example exit code for crash on Windows: `0xc000001d`.
Because of this, we define "crash" on all platforms as "not exit with
success and not exit with a regular failure code in the range 1..=127".

Some tests behave differently on different targets:
* Targets without unwind support will abort (crash) instead of exit with
  failure code 101 after panicking. As a special case, allow crashes for
  `run-fail` tests for such targets.
* Different sanitizer implementations handle detected memory problems
  differently. Some abort (crash) the process while others exit with
  failure code 1. Introduce and use `run-fail-or-crash` for such tests.
2025-07-19 18:44:07 +02:00

57 lines
1.7 KiB
Rust

// Verifies that ThreadSanitizer is able to detect a data race in heap allocated
// memory block.
//
// Test case minimizes the use of the standard library to avoid its ambiguous
// status with respect to instrumentation (it could vary depending on whatever
// a function call is inlined or not).
//
// The conflicting data access is de-facto synchronized with a special TSAN
// barrier, which does not introduce synchronization from TSAN perspective, but
// is necessary to make the test robust. Without the barrier data race detection
// would occasionally fail, making test flaky.
//
//@ needs-sanitizer-support
//@ needs-sanitizer-thread
//
//@ compile-flags: -Z sanitizer=thread -O
//
//@ run-fail-or-crash
//@ error-pattern: WARNING: ThreadSanitizer: data race
//@ error-pattern: Location is heap block of size 4
//@ error-pattern: allocated by main thread
#![feature(rustc_private)]
extern crate libc;
use std::mem;
use std::ptr;
static mut BARRIER: u64 = 0;
extern "C" {
fn __tsan_testonly_barrier_init(barrier: *mut u64, count: u32);
fn __tsan_testonly_barrier_wait(barrier: *mut u64);
}
extern "C" fn start(c: *mut libc::c_void) -> *mut libc::c_void {
unsafe {
let c: *mut u32 = c.cast();
*c += 1;
__tsan_testonly_barrier_wait(&raw mut BARRIER);
ptr::null_mut()
}
}
fn main() {
unsafe {
__tsan_testonly_barrier_init(&raw mut BARRIER, 2);
let c: *mut u32 = Box::into_raw(Box::new(1));
let mut t: libc::pthread_t = mem::zeroed();
libc::pthread_create(&mut t, ptr::null(), start, c.cast());
__tsan_testonly_barrier_wait(&raw mut BARRIER);
*c += 1;
libc::pthread_join(t, ptr::null_mut());
Box::from_raw(c);
}
}