Merge pull request #4059 from tiif/fixtest

Simplify thread blocking tests
This commit is contained in:
Oli Scherer 2024-11-26 07:29:30 +00:00 committed by GitHub
commit 63ce8fb322
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 21 additions and 52 deletions

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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
|

View file

@ -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();