@@ -69,17 +69,21 @@ pub struct EpollReadyEvents {
6969 /// Stream socket peer closed connection, or shut down writing
7070 /// half of connection.
7171 pub epollrdhup : bool ,
72+ /// For stream socket, this event merely indicates that the peer
73+ /// closed its end of the channel.
74+ pub epollhup : bool ,
7275}
7376
7477impl EpollReadyEvents {
7578 pub fn new ( ) -> Self {
76- EpollReadyEvents { epollin : false , epollout : false , epollrdhup : false }
79+ EpollReadyEvents { epollin : false , epollout : false , epollrdhup : false , epollhup : false }
7780 }
7881
7982 pub fn get_event_bitmask < ' tcx > ( & self , ecx : & MiriInterpCx < ' tcx > ) -> u32 {
8083 let epollin = ecx. eval_libc_u32 ( "EPOLLIN" ) ;
8184 let epollout = ecx. eval_libc_u32 ( "EPOLLOUT" ) ;
8285 let epollrdhup = ecx. eval_libc_u32 ( "EPOLLRDHUP" ) ;
86+ let epollhup = ecx. eval_libc_u32 ( "EPOLLHUP" ) ;
8387
8488 let mut bitmask = 0 ;
8589 if self . epollin {
@@ -91,6 +95,9 @@ impl EpollReadyEvents {
9195 if self . epollrdhup {
9296 bitmask |= epollrdhup;
9397 }
98+ if self . epollhup {
99+ bitmask |= epollhup;
100+ }
94101 bitmask
95102 }
96103}
@@ -217,6 +224,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
217224 let epollout = this. eval_libc_u32 ( "EPOLLOUT" ) ;
218225 let epollrdhup = this. eval_libc_u32 ( "EPOLLRDHUP" ) ;
219226 let epollet = this. eval_libc_u32 ( "EPOLLET" ) ;
227+ let epollhup = this. eval_libc_u32 ( "EPOLLHUP" ) ;
220228
221229 // Fail on unsupported operations.
222230 if op & epoll_ctl_add != epoll_ctl_add
@@ -244,11 +252,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
244252
245253 if op == epoll_ctl_add || op == epoll_ctl_mod {
246254 // Read event bitmask and data from epoll_event passed by caller.
247- let events = this. read_scalar ( & this. project_field ( & event, 0 ) ?) ?. to_u32 ( ) ?;
255+ let mut events = this. read_scalar ( & this. project_field ( & event, 0 ) ?) ?. to_u32 ( ) ?;
248256 let data = this. read_scalar ( & this. project_field ( & event, 1 ) ?) ?. to_u64 ( ) ?;
249257
250258 // Unset the flag we support to discover if any unsupported flags are used.
251259 let mut flags = events;
260+ // epoll_wait(2) will always wait for epollhup; it is not
261+ // necessary to set it in events when calling epoll_ctl().
262+ // So we will always set this event type.
263+ events |= epollhup;
264+
252265 if events & epollet != epollet {
253266 // We only support edge-triggered notification for now.
254267 throw_unsup_format ! ( "epoll_ctl: epollet flag must be included." ) ;
@@ -264,6 +277,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
264277 if flags & epollrdhup == epollrdhup {
265278 flags &= !epollrdhup;
266279 }
280+ if flags & epollhup == epollhup {
281+ flags &= !epollhup;
282+ }
267283 if flags != 0 {
268284 throw_unsup_format ! (
269285 "epoll_ctl: encountered unknown unsupported flags {:#x}" ,
0 commit comments