File tree Expand file tree Collapse file tree 3 files changed +17
-1
lines changed Expand file tree Collapse file tree 3 files changed +17
-1
lines changed Original file line number Diff line number Diff 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 ( ) ;
Original file line number Diff line number Diff 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) ) ;
Original file line number Diff line number Diff 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 ) ;
You can’t perform that action at this time.
0 commit comments