Skip to content

Commit 883e477

Browse files
committed
explain the behavior on closed peers
1 parent 9184eb5 commit 883e477

File tree

3 files changed

+12
-11
lines changed

3 files changed

+12
-11
lines changed

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -433,11 +433,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
433433
Ok(Scalar::from_i32(num_of_events))
434434
}
435435

436-
/// For a specific file description, get its ready events and update
437-
/// the corresponding ready list. This function is called whenever a file description
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!
436+
/// For a specific file description, get its ready events and update the corresponding ready
437+
/// list. This function should be called whenever an event causes more bytes or an EOF to become
438+
/// newly readable from an FD, and whenever more bytes can be written to an FD or no more future
439+
/// writes are possible.
440+
///
441+
/// This *will* report an event if anyone is subscribed to it, without any further filtering, so
442+
/// do not call this function when an FD didn't have anything happen to it!
441443
fn check_and_update_readiness(&self, fd_ref: &FileDescriptionRef) -> InterpResult<'tcx, ()> {
442444
let this = self.eval_context_ref();
443445
let id = fd_ref.get_id();

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ impl FileDescription for SocketPair {
7171
} else {
7272
// Peer FD has been closed.
7373
epoll_ready_events.epollrdhup = true;
74-
// This is an edge case. Whenever epollrdhup is triggered, epollin and epollout will be
75-
// added even though there is no data in the buffer.
76-
// FIXME: Figure out why. This looks like a bug.
74+
// Since the peer is closed, even if no data is available reads will return EOF and
75+
// writes will return EPIPE. In other words, they won't block, so we mark this as ready
76+
// for read and write.
7777
epoll_ready_events.epollin = true;
7878
epoll_ready_events.epollout = true;
7979
}
@@ -86,9 +86,7 @@ impl FileDescription for SocketPair {
8686
ecx: &mut MiriInterpCx<'tcx>,
8787
) -> InterpResult<'tcx, io::Result<()>> {
8888
if let Some(peer_fd) = self.peer_fd().upgrade() {
89-
// Notify peer fd that closed has happened.
90-
// When any of the events happened, we check and update the status of all supported events
91-
// types of peer fd.
89+
// Notify peer fd that close has happened, since that can unblock reads and writes.
9290
ecx.check_and_update_readiness(&peer_fd)?;
9391
}
9492
Ok(Ok(()))

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ fn test_epoll_socketpair() {
9696
assert_eq!(res, 0);
9797

9898
// Check result from epoll_wait.
99+
// We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer.
99100
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
100101
let expected_value = u64::try_from(fds[1]).unwrap();
101102
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));

0 commit comments

Comments
 (0)