Skip to content

Commit edd1efb

Browse files
committed
comment and test regarding notifications on writes that dont change readiness
1 parent b4ab820 commit edd1efb

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

src/tools/miri/src/shims/unix/linux/epoll.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl EpollEventInstance {
3535
EpollEventInstance { events, data }
3636
}
3737
}
38+
3839
/// EpollEventInterest registers the file description information to an epoll
3940
/// instance during a successful `epoll_ctl` call. It also stores additional
4041
/// information needed to check and update readiness state for `epoll_wait`.
@@ -434,7 +435,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
434435

435436
/// For a specific file description, get its ready events and update
436437
/// the corresponding ready list. This function is called whenever a file description
437-
/// is registered with epoll, or when its readiness *might* have changed.
438+
/// is registered with epoll, or the buffer it reads from / writes to changed.
439+
/// This *will* report an event if anyone is subscribed to it, without any further
440+
/// filtering, so do not call this function when an FD didn't have anything happen to it!
438441
fn check_and_update_readiness(&self, fd_ref: &FileDescriptionRef) -> InterpResult<'tcx, ()> {
439442
let this = self.eval_context_ref();
440443
let id = fd_ref.get_id();

src/tools/miri/src/shims/unix/socket.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ impl FileDescription for SocketPair {
200200
drop(writebuf);
201201

202202
// Notification should be provided for peer fd as it became readable.
203+
// The kernel does this even if the fd was already readable before, so we follow suit.
203204
ecx.check_and_update_readiness(&peer_fd)?;
204205

205206
return Ok(Ok(actual_write_size));

src/tools/miri/tests/pass-dep/libc/libc-epoll.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ fn test_epoll_socketpair() {
8383
let expected_value = u64::try_from(fds[1]).unwrap();
8484
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
8585

86+
// Check that this is indeed using "ET" (edge-trigger) semantics: a second epoll should return nothing.
87+
assert!(check_epoll_wait::<8>(epfd, vec![]));
88+
89+
// Write some more to fd[0].
90+
let data = "abcde".as_bytes().as_ptr();
91+
let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
92+
assert_eq!(res, 5);
93+
94+
// This did not change the readiness of fd[1]. And yet, we're seeing the event reported
95+
// again by the kernel, so Miri does the same.
96+
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
97+
8698
// Close the peer socketpair.
8799
let res = unsafe { libc::close(fds[0]) };
88100
assert_eq!(res, 0);

0 commit comments

Comments
 (0)