|
4 | 4 | // test_race depends on a deterministic schedule. |
5 | 5 | //@compile-flags: -Zmiri-deterministic-concurrency |
6 | 6 | //@error-in-other-file: deadlock |
| 7 | +//@require-annotations-for-level: error |
7 | 8 |
|
8 | 9 | use std::thread; |
9 | 10 |
|
| 11 | +#[path = "../../utils/libc.rs"] |
| 12 | +mod libc_utils; |
| 13 | + |
10 | 14 | // Test the behaviour of a thread being blocked on write, get unblocked, then blocked again. |
11 | 15 |
|
12 | 16 | // The expected execution is |
13 | 17 | // 1. Thread 1 blocks. |
14 | 18 | // 2. Thread 2 blocks. |
15 | 19 | // 3. Thread 3 unblocks both thread 1 and thread 2. |
16 | | -// 4. Thread 1 reads. |
| 20 | +// 4. Thread 1 writes. |
17 | 21 | // 5. Thread 2's `write` can never complete -> deadlocked. |
18 | 22 | fn main() { |
19 | 23 | let mut fds = [-1, -1]; |
20 | 24 | let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; |
21 | 25 | assert_eq!(res, 0); |
22 | 26 | let arr1: [u8; 212992] = [1; 212992]; |
23 | 27 | // Exhaust the space in the buffer so the subsequent write will block. |
24 | | - let res = unsafe { libc::write(fds[0], arr1.as_ptr() as *const libc::c_void, 212992) }; |
| 28 | + let res = |
| 29 | + unsafe { libc_utils::write_all(fds[0], arr1.as_ptr() as *const libc::c_void, 212992) }; |
25 | 30 | assert_eq!(res, 212992); |
26 | 31 | let thread1 = thread::spawn(move || { |
27 | | - let data = "abc".as_bytes().as_ptr(); |
| 32 | + let data = "a".as_bytes(); |
28 | 33 | // The write below will be blocked because the buffer is already full. |
29 | | - let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; |
30 | | - assert_eq!(res, 3); |
| 34 | + let res = unsafe { libc::write(fds[0], data.as_ptr() as *const libc::c_void, data.len()) }; |
| 35 | + assert_eq!(res, data.len().cast_signed()); |
31 | 36 | }); |
32 | 37 | let thread2 = thread::spawn(move || { |
33 | | - let data = "abc".as_bytes().as_ptr(); |
| 38 | + let data = "a".as_bytes(); |
34 | 39 | // The write below will be blocked because the buffer is already full. |
35 | | - let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; |
36 | | - //~^ERROR: deadlocked |
37 | | - assert_eq!(res, 3); |
| 40 | + let res = unsafe { libc::write(fds[0], data.as_ptr() as *const libc::c_void, data.len()) }; |
| 41 | + //~^ERROR: deadlock |
| 42 | + assert_eq!(res, data.len().cast_signed()); |
38 | 43 | }); |
39 | 44 | let thread3 = thread::spawn(move || { |
40 | 45 | // Unblock thread1 by freeing up some space. |
41 | | - let mut buf: [u8; 3] = [0; 3]; |
| 46 | + let mut buf: [u8; 1] = [0; 1]; |
42 | 47 | let res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; |
43 | | - assert_eq!(res, 3); |
44 | | - assert_eq!(buf, [1, 1, 1]); |
| 48 | + assert_eq!(res, buf.len().cast_signed()); |
| 49 | + assert_eq!(buf, [1]); |
45 | 50 | }); |
46 | 51 | thread1.join().unwrap(); |
47 | 52 | thread2.join().unwrap(); |
|
0 commit comments