Description
While looking at the situation where the last epoll changes for clock sync made it over sync, test cases were not being resolved as expected as the code was made less generous.
I think this showed a different problem in Miri that hadn't been reported yet.
Here is the problem demonstrated with the libc-socketpair in Miri, no epoll.
With this diff, the miri test fails in test_race3, indicating UB: data race. That's expected.
An exhibition of the problem, I think, is that test_race2 should also have a UB: data race reported, but it does not. And I believe it does not because the main thread was synced to the clock of the sub-thread, and that clock also covered the write to the global after what should have been the synchronizing event. The synchronizing event was only meant to build a happens-before relationship.
diff --git a/tests/pass-dep/libc/libc-socketpair.rs b/tests/pass-dep/libc/libc-socketpair.rs
index 64819e576..b38be4b92 100644
--- a/tests/pass-dep/libc/libc-socketpair.rs
+++ b/tests/pass-dep/libc/libc-socketpair.rs
@@ -10,6 +10,8 @@ fn main() {
test_socketpair();
test_socketpair_threaded();
test_race();
+ test_race2();
+ test_race3();
}
fn test_socketpair() {
@@ -136,3 +138,63 @@ fn test_race() {
thread::yield_now();
thread1.join().unwrap();
}
+
+fn test_race2() {
+ static mut VAL: u8 = 0;
+ let mut fds = [-1, -1];
+ let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+ assert_eq!(res, 0);
+ let thread1 = thread::spawn(move || {
+
+ let data = "a".as_bytes().as_ptr();
+ let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1) };
+ assert_eq!(res, 1);
+
+
+ unsafe { VAL = 1 };
+ });
+ thread::yield_now();
+
+ let mut buf: [u8; 1] = [0; 1];
+ let res: i32 = unsafe {
+ libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
+ .try_into()
+ .unwrap()
+ };
+ assert_eq!(res, 1);
+ assert_eq!(buf, "a".as_bytes());
+
+ unsafe { assert_eq!(VAL, 1) };
+
+ thread1.join().unwrap();
+}
+
+fn test_race3() {
+ static mut VAL: u8 = 0;
+ // let mut fds = [-1, -1];
+ // let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+ // assert_eq!(res, 0);
+ let thread1 = thread::spawn(move || {
+
+ // let data = "a".as_bytes().as_ptr();
+ // let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1) };
+ // assert_eq!(res, 1);
+
+
+ unsafe { VAL = 1 };
+ });
+ thread::yield_now();
+
+ // let mut buf: [u8; 1] = [0; 1];
+ // let res: i32 = unsafe {
+ // libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
+ // .try_into()
+ // .unwrap()
+ // };
+ // assert_eq!(res, 1);
+ // assert_eq!(buf, "a".as_bytes());
+
+ unsafe { assert_eq!(VAL, 1) };
+
+ thread1.join().unwrap();
+}