@@ -69,17 +69,21 @@ pub struct EpollReadyEvents {
69
69
/// Stream socket peer closed connection, or shut down writing
70
70
/// half of connection.
71
71
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 ,
72
75
}
73
76
74
77
impl EpollReadyEvents {
75
78
pub fn new ( ) -> Self {
76
- EpollReadyEvents { epollin : false , epollout : false , epollrdhup : false }
79
+ EpollReadyEvents { epollin : false , epollout : false , epollrdhup : false , epollhup : false }
77
80
}
78
81
79
82
pub fn get_event_bitmask < ' tcx > ( & self , ecx : & MiriInterpCx < ' tcx > ) -> u32 {
80
83
let epollin = ecx. eval_libc_u32 ( "EPOLLIN" ) ;
81
84
let epollout = ecx. eval_libc_u32 ( "EPOLLOUT" ) ;
82
85
let epollrdhup = ecx. eval_libc_u32 ( "EPOLLRDHUP" ) ;
86
+ let epollhup = ecx. eval_libc_u32 ( "EPOLLHUP" ) ;
83
87
84
88
let mut bitmask = 0 ;
85
89
if self . epollin {
@@ -91,6 +95,9 @@ impl EpollReadyEvents {
91
95
if self . epollrdhup {
92
96
bitmask |= epollrdhup;
93
97
}
98
+ if self . epollhup {
99
+ bitmask |= epollhup;
100
+ }
94
101
bitmask
95
102
}
96
103
}
@@ -217,6 +224,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
217
224
let epollout = this. eval_libc_u32 ( "EPOLLOUT" ) ;
218
225
let epollrdhup = this. eval_libc_u32 ( "EPOLLRDHUP" ) ;
219
226
let epollet = this. eval_libc_u32 ( "EPOLLET" ) ;
227
+ let epollhup = this. eval_libc_u32 ( "EPOLLHUP" ) ;
220
228
221
229
// Fail on unsupported operations.
222
230
if op & epoll_ctl_add != epoll_ctl_add
@@ -244,11 +252,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
244
252
245
253
if op == epoll_ctl_add || op == epoll_ctl_mod {
246
254
// 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 ( ) ?;
248
256
let data = this. read_scalar ( & this. project_field ( & event, 1 ) ?) ?. to_u64 ( ) ?;
249
257
250
258
// Unset the flag we support to discover if any unsupported flags are used.
251
259
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
+
252
265
if events & epollet != epollet {
253
266
// We only support edge-triggered notification for now.
254
267
throw_unsup_format ! ( "epoll_ctl: epollet flag must be included." ) ;
@@ -264,6 +277,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
264
277
if flags & epollrdhup == epollrdhup {
265
278
flags &= !epollrdhup;
266
279
}
280
+ if flags & epollhup == epollhup {
281
+ flags &= !epollhup;
282
+ }
267
283
if flags != 0 {
268
284
throw_unsup_format ! (
269
285
"epoll_ctl: encountered unknown unsupported flags {:#x}" ,
0 commit comments