diff options
| author | bors <bors@rust-lang.org> | 2024-08-16 16:14:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-08-16 16:14:42 +0000 |
| commit | 83f1b380825d50e3cffe84ef4c39a09bf841a3c1 (patch) | |
| tree | c70b68a567305becd89e4a26a0c37d07b7a2a370 /src/tools/miri/tests | |
| parent | 1a51dd9247c5ecf9efa99ebf644bb12e33dcf3b5 (diff) | |
| parent | 883e4773b30f652e83326df99dc0ec7d652e1f94 (diff) | |
| download | rust-83f1b380825d50e3cffe84ef4c39a09bf841a3c1.tar.gz rust-83f1b380825d50e3cffe84ef4c39a09bf841a3c1.zip | |
Auto merge of #3809 - RalfJung:fd-refcell, r=oli-obk
FD: remove big surrounding RefCell, simplify socketpair A while ago, I added the big implicit RefCell for all file descriptions since it avoided interior mutability in `eventfd`. However, this requires us to hold the RefCell "lock" around the entire invocation of the `read`/`write` methods on an FD, which is not great. For instance, if an FD wants to update epoll notifications from inside its `read`/`write`, it is very crucial that the notification check does not end up accessing the FD itself. Such cycles, however, occur naturally: - eventfd wants to update notifications for itself - socketfd wants to update notifications on its "peer", which will in turn check *its* peer to see whether that buffer is empty -- and my peer's peer is myself. This then also lets us simplify socketpair, which currently holds a weak reference to its peer *and* a weak reference to the peer's buffer -- that was previously needed precisely to avoid this issue.
Diffstat (limited to 'src/tools/miri/tests')
| -rw-r--r-- | src/tools/miri/tests/pass-dep/libc/libc-epoll.rs | 243 |
1 files changed, 98 insertions, 145 deletions
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs index 11a0257dc4e..841761e53dd 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs @@ -5,34 +5,40 @@ use std::convert::TryInto; use std::mem::MaybeUninit; fn main() { + test_epoll_socketpair(); + test_epoll_socketpair_both_sides(); + test_socketpair_read(); + test_epoll_eventfd(); + test_event_overwrite(); test_not_fully_closed_fd(); test_closed_fd(); - test_epoll_socketpair_special_case(); test_two_epoll_instance(); test_epoll_ctl_mod(); - test_epoll_socketpair(); - test_epoll_eventfd(); test_epoll_ctl_del(); test_pointer(); test_two_same_fd_in_same_epoll_instance(); - test_socketpair_read(); } -fn check_epoll_wait<const N: usize>( - epfd: i32, - mut expected_notifications: Vec<(u32, u64)>, -) -> bool { +// Using `as` cast since `EPOLLET` wraps around +const EPOLL_IN_OUT_ET: u32 = (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _; + +#[track_caller] +fn check_epoll_wait<const N: usize>(epfd: i32, expected_notifications: &[(u32, u64)]) -> bool { let epoll_event = libc::epoll_event { events: 0, u64: 0 }; let mut array: [libc::epoll_event; N] = [epoll_event; N]; let maxsize = N; let array_ptr = array.as_mut_ptr(); let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) }; + if res < 0 { + panic!("epoll_wait failed: {}", std::io::Error::last_os_error()); + } assert_eq!(res, expected_notifications.len().try_into().unwrap()); let slice = unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) }; let mut return_events = slice.iter(); + let mut expected_notifications = expected_notifications.iter(); while let Some(return_event) = return_events.next() { - if let Some(notification) = expected_notifications.pop() { + if let Some(notification) = expected_notifications.next() { let event = return_event.events; let data = return_event.u64; assert_eq!(event, notification.0); @@ -41,10 +47,8 @@ fn check_epoll_wait<const N: usize>( return false; } } - if !expected_notifications.is_empty() { - return false; - } - return true; + // There shouldn't be any more expected. + return expected_notifications.next().is_none(); } fn test_epoll_socketpair() { @@ -54,21 +58,17 @@ fn test_epoll_socketpair() { // Create a socketpair instance. let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); // Write to fd[0] let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; assert_eq!(res, 5); - // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLRDHUP).unwrap() | epollet; + // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) as _, u64: u64::try_from(fds[1]).unwrap(), }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; @@ -77,16 +77,29 @@ fn test_epoll_socketpair() { // Check result from epoll_wait. let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fds[1]).unwrap(); - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); + + // Check that this is indeed using "ET" (edge-trigger) semantics: a second epoll should return nothing. + assert!(check_epoll_wait::<8>(epfd, &[])); + + // Write some more to fd[0]. + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + + // This did not change the readiness of fd[1]. And yet, we're seeing the event reported + // again by the kernel, so Miri does the same. + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); // Close the peer socketpair. let res = unsafe { libc::close(fds[0]) }; assert_eq!(res, 0); // Check result from epoll_wait. + // We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer. let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fds[1]).unwrap(); - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); } fn test_epoll_ctl_mod() { @@ -96,35 +109,28 @@ fn test_epoll_ctl_mod() { // Create a socketpair instance. let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); // Write to fd[0]. let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; assert_eq!(res, 5); // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET. - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let mut flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: u64::try_from(fds[1]).unwrap(), - }; + // (Not using checked cast as EPOLLET wraps around.) + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); // Check result from epoll_wait. let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fds[1]).unwrap(); - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); // Test EPOLLRDHUP. - flags |= u32::try_from(libc::EPOLLRDHUP).unwrap(); let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) as _, u64: u64::try_from(fds[1]).unwrap(), }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_MOD, fds[1], &mut ev) }; @@ -137,7 +143,7 @@ fn test_epoll_ctl_mod() { // Check result from epoll_wait. let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fds[1]).unwrap(); - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); } fn test_epoll_ctl_del() { @@ -147,28 +153,21 @@ fn test_epoll_ctl_del() { // Create a socketpair instance. let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); // Write to fd[0] let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; assert_eq!(res, 5); // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: u64::try_from(fds[1]).unwrap(), - }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); // Test EPOLL_CTL_DEL. - assert!(check_epoll_wait::<0>(epfd, vec![])); + assert!(check_epoll_wait::<0>(epfd, &[])); } // This test is for one fd registered under two different epoll instance. @@ -181,22 +180,16 @@ fn test_two_epoll_instance() { // Create a socketpair instance. let mut fds = [-1, -1]; - let mut res = - unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; + let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; assert_eq!(res, 0); // Write to the socketpair. let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; assert_eq!(res, 5); // Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: u64::try_from(fds[1]).unwrap(), - }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() }; let res = unsafe { libc::epoll_ctl(epfd1, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); let res = unsafe { libc::epoll_ctl(epfd2, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; @@ -205,8 +198,8 @@ fn test_two_epoll_instance() { // Notification should be received from both instance of epoll. let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fds[1]).unwrap(); - assert!(check_epoll_wait::<8>(epfd1, vec![(expected_event, expected_value)])); - assert!(check_epoll_wait::<8>(epfd2, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd1, &[(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd2, &[(expected_event, expected_value)])); } // This test is for two same file description registered under the same epoll instance through dup. @@ -226,17 +219,15 @@ fn test_two_same_fd_in_same_epoll_instance() { assert_ne!(newfd, -1); // Register both fd to the same epoll instance. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: 5 as u64 }; - let mut res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: 5 as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); - res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) }; assert_ne!(res, -1); // Write to the socketpair. let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) }; assert_eq!(res, 5); //Two notification should be received. @@ -244,7 +235,7 @@ fn test_two_same_fd_in_same_epoll_instance() { let expected_value = 5 as u64; assert!(check_epoll_wait::<8>( epfd, - vec![(expected_event, expected_value), (expected_event, expected_value)] + &[(expected_event, expected_value), (expected_event, expected_value)] )); } @@ -255,9 +246,7 @@ fn test_epoll_eventfd() { // Write to the eventfd instance. let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); - let res: i32 = unsafe { - libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() - }; + let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; assert_eq!(res, 8); // Create an epoll instance. @@ -265,20 +254,14 @@ fn test_epoll_eventfd() { assert_ne!(epfd, -1); // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: u64::try_from(fd).unwrap(), - }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; assert_ne!(res, -1); // Check result from epoll_wait. let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fd).unwrap(); - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); } fn test_pointer() { @@ -292,20 +275,15 @@ fn test_pointer() { assert_eq!(res, 0); // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLRDHUP).unwrap() | epollet; let data = MaybeUninit::<u64>::uninit().as_ptr(); - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: data.expose_provenance() as u64, - }; + let mut ev = + libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: data.expose_provenance() as u64 }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); } // When read/write happened on one side of the socketpair, only the other side will be notified. -fn test_epoll_socketpair_special_case() { +fn test_epoll_socketpair_both_sides() { // Create an epoll instance. let epfd = unsafe { libc::epoll_create1(0) }; assert_ne!(epfd, -1); @@ -316,18 +294,16 @@ fn test_epoll_socketpair_special_case() { assert_eq!(res, 0); // Register both fd to the same epoll instance. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[0] as u64 }; - let mut res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[0] as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; assert_ne!(res, -1); - let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[1] as u64 }; - res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[1] as u64 }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); // Write to fds[1]. let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; assert_eq!(res, 5); //Two notification should be received. @@ -337,21 +313,19 @@ fn test_epoll_socketpair_special_case() { let expected_value1 = fds[1] as u64; assert!(check_epoll_wait::<8>( epfd, - vec![(expected_event1, expected_value1), (expected_event0, expected_value0)] + &[(expected_event0, expected_value0), (expected_event1, expected_value1)] )); // Read from fds[0]. let mut buf: [u8; 5] = [0; 5]; - res = unsafe { - libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; assert_eq!(res, 5); assert_eq!(buf, "abcde".as_bytes()); // Notification should be provided for fds[1]. let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value = fds[1] as u64; - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); } // When file description is fully closed, epoll_wait should not provide any notification for @@ -366,21 +340,13 @@ fn test_closed_fd() { let fd = unsafe { libc::eventfd(0, flags) }; // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: u64::try_from(fd).unwrap(), - }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; assert_ne!(res, -1); // Write to the eventfd instance. let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); - let res: i32 = unsafe { - libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() - }; + let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; assert_eq!(res, 8); // Close the eventfd. @@ -388,7 +354,7 @@ fn test_closed_fd() { assert_eq!(res, 0); // No notification should be provided because the file description is closed. - assert!(check_epoll_wait::<8>(epfd, vec![])); + assert!(check_epoll_wait::<8>(epfd, &[])); } // When a certain file descriptor registered with epoll is closed, but the underlying file description @@ -411,13 +377,7 @@ fn test_not_fully_closed_fd() { assert_ne!(newfd, -1); // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), - u64: u64::try_from(fd).unwrap(), - }; + let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; assert_ne!(res, -1); @@ -428,13 +388,11 @@ fn test_not_fully_closed_fd() { // Notification should still be provided because the file description is not closed. let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value = fd as u64; - assert!(check_epoll_wait::<1>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)])); // Write to the eventfd instance to produce notification. let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); - let res: i32 = unsafe { - libc::write(newfd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() - }; + let res = unsafe { libc::write(newfd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; assert_eq!(res, 8); // Close the dupped fd. @@ -442,7 +400,7 @@ fn test_not_fully_closed_fd() { assert_eq!(res, 0); // No notification should be provided. - assert!(check_epoll_wait::<1>(epfd, vec![])); + assert!(check_epoll_wait::<1>(epfd, &[])); } // Each time a notification is provided, it should reflect the file description's readiness @@ -454,9 +412,7 @@ fn test_event_overwrite() { // Write to the eventfd instance. let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes(); - let res: i32 = unsafe { - libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() - }; + let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) }; assert_eq!(res, 8); // Create an epoll instance. @@ -464,11 +420,8 @@ fn test_event_overwrite() { assert_ne!(epfd, -1); // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET - // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; let mut ev = libc::epoll_event { - events: u32::try_from(flags).unwrap(), + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _, u64: u64::try_from(fd).unwrap(), }; let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) }; @@ -476,13 +429,13 @@ fn test_event_overwrite() { // Read from the eventfd instance. let mut buf: [u8; 8] = [0; 8]; - let res: i32 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() }; + let res = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8) }; assert_eq!(res, 8); // Check result from epoll_wait. let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value = u64::try_from(fd).unwrap(); - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); } // An epoll notification will be provided for every succesful read in a socketpair. @@ -498,18 +451,22 @@ fn test_socketpair_read() { assert_eq!(res, 0); // Register both fd to the same epoll instance. - let epollet = libc::EPOLLET as u32; - let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet; - let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[0] as u64 }; - let mut res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _, + u64: fds[0] as u64, + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) }; assert_ne!(res, -1); - let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[1] as u64 }; - res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; + let mut ev = libc::epoll_event { + events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _, + u64: fds[1] as u64, + }; + let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) }; assert_ne!(res, -1); // Write 5 bytes to fds[1]. let data = "abcde".as_bytes().as_ptr(); - res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() }; + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; assert_eq!(res, 5); //Two notification should be received. @@ -519,14 +476,12 @@ fn test_socketpair_read() { let expected_value1 = fds[1] as u64; assert!(check_epoll_wait::<8>( epfd, - vec![(expected_event1, expected_value1), (expected_event0, expected_value0)] + &[(expected_event0, expected_value0), (expected_event1, expected_value1)] )); // Read 3 bytes from fds[0]. let mut buf: [u8; 3] = [0; 3]; - res = unsafe { - libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; assert_eq!(res, 3); assert_eq!(buf, "abc".as_bytes()); @@ -534,13 +489,11 @@ fn test_socketpair_read() { // But in real system, no notification will be provided here. let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value = fds[1] as u64; - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); // Read until the buffer is empty. let mut buf: [u8; 2] = [0; 2]; - res = unsafe { - libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap() - }; + let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; assert_eq!(res, 2); assert_eq!(buf, "de".as_bytes()); @@ -548,5 +501,5 @@ fn test_socketpair_read() { // In real system, notification will be provided too. let expected_event = u32::try_from(libc::EPOLLOUT).unwrap(); let expected_value = fds[1] as u64; - assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)])); + assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)])); } |
