Skip to content

Commit 75209df

Browse files
committed
add test for close-while-blocked
1 parent 16cffc7 commit 75209df

File tree

3 files changed

+78
-8
lines changed

3 files changed

+78
-8
lines changed

src/tools/miri/src/shims/unix/unnamed_socket.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,9 @@ fn anonsocket_write<'tcx>(
167167
dest: MPlaceTy<'tcx>,
168168
}
169169
@unblock = |this| {
170-
let Some(self_ref) = weak_self_ref.upgrade() else {
171-
// FIXME: We should raise a deadlock error if the self_ref upgrade failed.
172-
throw_unsup_format!("This will be a deadlock error in future")
173-
};
170+
// If we got unblocked, then our peer successfully upgraded its weak
171+
// ref to us. That means we can also upgrade our weak ref.
172+
let self_ref = weak_self_ref.upgrade().unwrap();
174173
anonsocket_write(&self_ref, ptr, len, &dest, this)
175174
}
176175
),
@@ -257,10 +256,9 @@ fn anonsocket_read<'tcx>(
257256
dest: MPlaceTy<'tcx>,
258257
}
259258
@unblock = |this| {
260-
let Some(self_ref) = weak_self_ref.upgrade() else {
261-
// FIXME: We should raise a deadlock error if the self_ref upgrade failed.
262-
throw_unsup_format!("This will be a deadlock error in future")
263-
};
259+
// If we got unblocked, then our peer successfully upgraded its weak
260+
// ref to us. That means we can also upgrade our weak ref.
261+
let self_ref = weak_self_ref.upgrade().unwrap();
264262
anonsocket_read(&self_ref, len, ptr, &dest, this)
265263
}
266264
),
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//! This is a regression test for <https://github.com/rust-lang/miri/issues/3947>: we had some
2+
//! faulty logic around `release_clock` that led to this code not reporting a data race.
3+
//~^^ERROR: deadlock
4+
//@ignore-target: windows # no libc socketpair on Windows
5+
//@compile-flags: -Zmiri-preemption-rate=0 -Zmiri-address-reuse-rate=0
6+
//@error-in-other-file: deadlock
7+
use std::thread;
8+
9+
fn main() {
10+
let mut fds = [-1, -1];
11+
let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
12+
assert_eq!(res, 0);
13+
14+
let thread1 = thread::spawn(move || {
15+
let mut buf: [u8; 1] = [0; 1];
16+
let _res: i32 = unsafe {
17+
libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) //~ERROR: deadlock
18+
.try_into()
19+
.unwrap()
20+
};
21+
});
22+
let thread2 = thread::spawn(move || {
23+
// Close the FD that the other thread is blocked on.
24+
unsafe { libc::close(fds[1]) };
25+
});
26+
27+
// Run the other threads.
28+
thread::yield_now();
29+
30+
// When they are both done, continue here.
31+
let data = "a".as_bytes().as_ptr();
32+
let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 1) };
33+
assert_eq!(res, -1);
34+
35+
thread1.join().unwrap();
36+
thread2.join().unwrap();
37+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: deadlock: the evaluated program deadlocked
2+
--> RUSTLIB/std/src/sys/pal/PLATFORM/thread.rs:LL:CC
3+
|
4+
LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };
5+
| ^ the evaluated program deadlocked
6+
|
7+
= note: BACKTRACE:
8+
= note: inside `std::sys::pal::PLATFORM::thread::Thread::join` at RUSTLIB/std/src/sys/pal/PLATFORM/thread.rs:LL:CC
9+
= note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
10+
= note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
11+
note: inside `main`
12+
--> tests/fail-dep/libc/socketpair-close-while-blocked.rs:LL:CC
13+
|
14+
LL | thread1.join().unwrap();
15+
| ^^^^^^^^^^^^^^
16+
17+
error: deadlock: the evaluated program deadlocked
18+
--> tests/fail-dep/libc/socketpair-close-while-blocked.rs:LL:CC
19+
|
20+
LL | libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t)
21+
| ^ the evaluated program deadlocked
22+
|
23+
= note: BACKTRACE on thread `unnamed-ID`:
24+
= note: inside closure at tests/fail-dep/libc/socketpair-close-while-blocked.rs:LL:CC
25+
26+
error: deadlock: the evaluated program deadlocked
27+
|
28+
= note: the evaluated program deadlocked
29+
= note: (no span available)
30+
= note: BACKTRACE on thread `unnamed-ID`:
31+
32+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
33+
34+
error: aborting due to 3 previous errors
35+

0 commit comments

Comments
 (0)