]> git.lizzy.rs Git - rust.git/commitdiff
Add ThreadSanitizer test case
authorTomasz Miąsko <tomasz.miasko@gmail.com>
Thu, 9 Apr 2020 00:00:00 +0000 (00:00 +0000)
committerTomasz Miąsko <tomasz.miasko@gmail.com>
Fri, 10 Apr 2020 14:29:09 +0000 (16:29 +0200)
src/test/ui/sanitize/thread.rs [new file with mode: 0644]

diff --git a/src/test/ui/sanitize/thread.rs b/src/test/ui/sanitize/thread.rs
new file mode 100644 (file)
index 0000000..26590be
--- /dev/null
@@ -0,0 +1,57 @@
+// 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
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=thread -O
+//
+// run-fail
+// error-pattern: WARNING: ThreadSanitizer: data race
+// error-pattern: Location is heap block of size 4
+// error-pattern: allocated by main thread
+
+#![feature(raw_ref_op)]
+#![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);
+    }
+}