Simplify thread blocking tests
This commit is contained in:
parent
d12594570a
commit
109c299646
5 changed files with 21 additions and 52 deletions
|
|
@ -23,7 +23,6 @@ fn main() {
|
|||
let fd = unsafe { libc::eventfd(0, flags) };
|
||||
|
||||
let thread1 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
// This read will block initially.
|
||||
let res: i64 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() };
|
||||
|
|
@ -33,7 +32,6 @@ fn main() {
|
|||
});
|
||||
|
||||
let thread2 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
// This read will block initially, then get unblocked by thread3, then get blocked again
|
||||
// because the `read` in thread1 executes first and set the counter to 0 again.
|
||||
|
|
@ -45,7 +43,6 @@ fn main() {
|
|||
});
|
||||
|
||||
let thread3 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let sized_8_data = 1_u64.to_ne_bytes();
|
||||
// Write 1 to the counter, so both thread1 and thread2 will unblock.
|
||||
let res: i64 = unsafe {
|
||||
|
|
@ -55,10 +52,6 @@ fn main() {
|
|||
assert_eq!(res, 8);
|
||||
});
|
||||
|
||||
thread1.thread().unpark();
|
||||
thread2.thread().unpark();
|
||||
thread3.thread().unpark();
|
||||
|
||||
thread1.join().unwrap();
|
||||
thread2.join().unwrap();
|
||||
thread3.join().unwrap();
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ fn main() {
|
|||
assert_eq!(res, 8);
|
||||
|
||||
let thread1 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let sized_8_data = (u64::MAX - 1).to_ne_bytes();
|
||||
let res: i64 = unsafe {
|
||||
libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
|
||||
|
|
@ -38,7 +37,6 @@ fn main() {
|
|||
});
|
||||
|
||||
let thread2 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let sized_8_data = (u64::MAX - 1).to_ne_bytes();
|
||||
// Write u64::MAX - 1, so the all subsequent write will block.
|
||||
let res: i64 = unsafe {
|
||||
|
|
@ -52,7 +50,6 @@ fn main() {
|
|||
});
|
||||
|
||||
let thread3 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
// This will unblock both `write` in thread1 and thread2.
|
||||
let res: i64 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() };
|
||||
|
|
@ -61,10 +58,6 @@ fn main() {
|
|||
assert_eq!(counter, (u64::MAX - 1));
|
||||
});
|
||||
|
||||
thread1.thread().unpark();
|
||||
thread2.thread().unpark();
|
||||
thread3.thread().unpark();
|
||||
|
||||
thread1.join().unwrap();
|
||||
thread2.join().unwrap();
|
||||
thread3.join().unwrap();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
//@error-in-other-file: deadlock
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::thread;
|
||||
use std::thread::spawn;
|
||||
|
||||
// Using `as` cast since `EPOLLET` wraps around
|
||||
|
|
@ -41,10 +40,10 @@ fn check_epoll_wait<const N: usize>(
|
|||
|
||||
// Test if only one thread is unblocked if multiple threads blocked on same epfd.
|
||||
// Expected execution:
|
||||
// 1. Thread 2 blocks.
|
||||
// 2. Thread 3 blocks.
|
||||
// 3. Thread 1 unblocks thread 3.
|
||||
// 4. Thread 2 deadlocks.
|
||||
// 1. Thread 1 blocks.
|
||||
// 2. Thread 2 blocks.
|
||||
// 3. Thread 3 unblocks thread 2.
|
||||
// 4. Thread 1 deadlocks.
|
||||
fn main() {
|
||||
// Create an epoll instance.
|
||||
let epfd = unsafe { libc::epoll_create1(0) };
|
||||
|
|
@ -65,31 +64,22 @@ fn main() {
|
|||
let expected_value = fds[0] as u64;
|
||||
check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], 0);
|
||||
|
||||
let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
|
||||
let expected_value = fds[0] as u64;
|
||||
let thread1 = spawn(move || {
|
||||
thread::park();
|
||||
check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1);
|
||||
//~^ERROR: deadlocked
|
||||
});
|
||||
let thread2 = spawn(move || {
|
||||
check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1);
|
||||
});
|
||||
|
||||
let thread3 = spawn(move || {
|
||||
let data = "abcde".as_bytes().as_ptr();
|
||||
let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
|
||||
assert_eq!(res, 5);
|
||||
});
|
||||
|
||||
let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
|
||||
let expected_value = fds[0] as u64;
|
||||
let thread2 = spawn(move || {
|
||||
thread::park();
|
||||
check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1);
|
||||
//~^ERROR: deadlocked
|
||||
});
|
||||
let thread3 = spawn(move || {
|
||||
thread::park();
|
||||
check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1);
|
||||
});
|
||||
|
||||
thread2.thread().unpark();
|
||||
thread::yield_now();
|
||||
thread3.thread().unpark();
|
||||
thread::yield_now();
|
||||
thread1.thread().unpark();
|
||||
|
||||
thread1.join().unwrap();
|
||||
thread2.join().unwrap();
|
||||
thread3.join().unwrap();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
error: deadlock: the evaluated program deadlocked
|
||||
|
|
||||
= note: the evaluated program deadlocked
|
||||
= note: (no span available)
|
||||
= note: BACKTRACE on thread `unnamed-ID`:
|
||||
|
||||
error: deadlock: the evaluated program deadlocked
|
||||
--> RUSTLIB/std/src/sys/pal/PLATFORM/thread.rs:LL:CC
|
||||
|
|
||||
|
|
@ -11,15 +17,9 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };
|
|||
note: inside `main`
|
||||
--> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC
|
||||
|
|
||||
LL | thread2.join().unwrap();
|
||||
LL | thread1.join().unwrap();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: deadlock: the evaluated program deadlocked
|
||||
|
|
||||
= note: the evaluated program deadlocked
|
||||
= note: (no span available)
|
||||
= note: BACKTRACE on thread `unnamed-ID`:
|
||||
|
||||
error: deadlock: the evaluated program deadlocked
|
||||
--> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC
|
||||
|
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ fn test_two_threads_blocked_on_eventfd() {
|
|||
assert_eq!(res, 8);
|
||||
|
||||
let thread1 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let sized_8_data = 1_u64.to_ne_bytes();
|
||||
let res: i64 = unsafe {
|
||||
libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
|
||||
|
|
@ -207,7 +206,6 @@ fn test_two_threads_blocked_on_eventfd() {
|
|||
});
|
||||
|
||||
let thread2 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let sized_8_data = 1_u64.to_ne_bytes();
|
||||
let res: i64 = unsafe {
|
||||
libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
|
||||
|
|
@ -217,7 +215,6 @@ fn test_two_threads_blocked_on_eventfd() {
|
|||
});
|
||||
|
||||
let thread3 = thread::spawn(move || {
|
||||
thread::park();
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
// This will unblock previously blocked eventfd read.
|
||||
let res = read_bytes(fd, &mut buf);
|
||||
|
|
@ -227,10 +224,6 @@ fn test_two_threads_blocked_on_eventfd() {
|
|||
assert_eq!(counter, (u64::MAX - 1));
|
||||
});
|
||||
|
||||
thread1.thread().unpark();
|
||||
thread2.thread().unpark();
|
||||
thread3.thread().unpark();
|
||||
|
||||
thread1.join().unwrap();
|
||||
thread2.join().unwrap();
|
||||
thread3.join().unwrap();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue