File tree 3 files changed +17
-1
lines changed
3 files changed +17
-1
lines changed Original file line number Diff line number Diff line change @@ -35,6 +35,7 @@ impl EpollEventInstance {
35
35
EpollEventInstance { events, data }
36
36
}
37
37
}
38
+
38
39
/// EpollEventInterest registers the file description information to an epoll
39
40
/// instance during a successful `epoll_ctl` call. It also stores additional
40
41
/// information needed to check and update readiness state for `epoll_wait`.
@@ -434,7 +435,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
434
435
435
436
/// For a specific file description, get its ready events and update
436
437
/// 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!
438
441
fn check_and_update_readiness ( & self , fd_ref : & FileDescriptionRef ) -> InterpResult < ' tcx , ( ) > {
439
442
let this = self . eval_context_ref ( ) ;
440
443
let id = fd_ref. get_id ( ) ;
Original file line number Diff line number Diff line change @@ -200,6 +200,7 @@ impl FileDescription for SocketPair {
200
200
drop ( writebuf) ;
201
201
202
202
// 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.
203
204
ecx. check_and_update_readiness ( & peer_fd) ?;
204
205
205
206
return Ok ( Ok ( actual_write_size) ) ;
Original file line number Diff line number Diff line change @@ -83,6 +83,18 @@ fn test_epoll_socketpair() {
83
83
let expected_value = u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ;
84
84
assert ! ( check_epoll_wait:: <8 >( epfd, vec![ ( expected_event, expected_value) ] ) ) ;
85
85
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
+
86
98
// Close the peer socketpair.
87
99
let res = unsafe { libc:: close ( fds[ 0 ] ) } ;
88
100
assert_eq ! ( res, 0 ) ;
You can’t perform that action at this time.
0 commit comments