|
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