Skip to content

Commit 0951107

Browse files
committed
Add epoll EPOLLHUP flag support
1 parent 83f1b38 commit 0951107

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7477
impl 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}",

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ impl FileDescription for SocketPair {
4949
}
5050

5151
fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
52-
// We only check the status of EPOLLIN, EPOLLOUT and EPOLLRDHUP flags. If other event flags
53-
// need to be supported in the future, the check should be added here.
52+
// We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags.
53+
// If other event flags need to be supported in the future, the check should be added here.
5454

5555
let mut epoll_ready_events = EpollReadyEvents::new();
5656

@@ -76,6 +76,7 @@ impl FileDescription for SocketPair {
7676
// for read and write.
7777
epoll_ready_events.epollin = true;
7878
epoll_ready_events.epollout = true;
79+
epoll_ready_events.epollhup = true;
7980
}
8081
Ok(epoll_ready_events)
8182
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ fn test_epoll_socketpair() {
9797

9898
// Check result from epoll_wait.
9999
// We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer.
100-
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
100+
let expected_event =
101+
u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP).unwrap();
101102
let expected_value = u64::try_from(fds[1]).unwrap();
102103
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
103104
}
@@ -141,7 +142,8 @@ fn test_epoll_ctl_mod() {
141142
assert_eq!(res, 0);
142143

143144
// Check result from epoll_wait.
144-
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
145+
let expected_event =
146+
u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP).unwrap();
145147
let expected_value = u64::try_from(fds[1]).unwrap();
146148
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
147149
}

0 commit comments

Comments
 (0)