Add epoll EPOLLHUP flag support
This commit is contained in:
parent
83f1b38082
commit
0951107881
@ -69,17 +69,21 @@ pub struct EpollReadyEvents {
|
|||||||
/// Stream socket peer closed connection, or shut down writing
|
/// Stream socket peer closed connection, or shut down writing
|
||||||
/// half of connection.
|
/// half of connection.
|
||||||
pub epollrdhup: bool,
|
pub epollrdhup: bool,
|
||||||
|
/// For stream socket, this event merely indicates that the peer
|
||||||
|
/// closed its end of the channel.
|
||||||
|
pub epollhup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EpollReadyEvents {
|
impl EpollReadyEvents {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
EpollReadyEvents { epollin: false, epollout: false, epollrdhup: false }
|
EpollReadyEvents { epollin: false, epollout: false, epollrdhup: false, epollhup: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_event_bitmask<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> u32 {
|
pub fn get_event_bitmask<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> u32 {
|
||||||
let epollin = ecx.eval_libc_u32("EPOLLIN");
|
let epollin = ecx.eval_libc_u32("EPOLLIN");
|
||||||
let epollout = ecx.eval_libc_u32("EPOLLOUT");
|
let epollout = ecx.eval_libc_u32("EPOLLOUT");
|
||||||
let epollrdhup = ecx.eval_libc_u32("EPOLLRDHUP");
|
let epollrdhup = ecx.eval_libc_u32("EPOLLRDHUP");
|
||||||
|
let epollhup = ecx.eval_libc_u32("EPOLLHUP");
|
||||||
|
|
||||||
let mut bitmask = 0;
|
let mut bitmask = 0;
|
||||||
if self.epollin {
|
if self.epollin {
|
||||||
@ -91,6 +95,9 @@ pub fn get_event_bitmask<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> u32 {
|
|||||||
if self.epollrdhup {
|
if self.epollrdhup {
|
||||||
bitmask |= epollrdhup;
|
bitmask |= epollrdhup;
|
||||||
}
|
}
|
||||||
|
if self.epollhup {
|
||||||
|
bitmask |= epollhup;
|
||||||
|
}
|
||||||
bitmask
|
bitmask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,6 +224,7 @@ fn epoll_ctl(
|
|||||||
let epollout = this.eval_libc_u32("EPOLLOUT");
|
let epollout = this.eval_libc_u32("EPOLLOUT");
|
||||||
let epollrdhup = this.eval_libc_u32("EPOLLRDHUP");
|
let epollrdhup = this.eval_libc_u32("EPOLLRDHUP");
|
||||||
let epollet = this.eval_libc_u32("EPOLLET");
|
let epollet = this.eval_libc_u32("EPOLLET");
|
||||||
|
let epollhup = this.eval_libc_u32("EPOLLHUP");
|
||||||
|
|
||||||
// Fail on unsupported operations.
|
// Fail on unsupported operations.
|
||||||
if op & epoll_ctl_add != epoll_ctl_add
|
if op & epoll_ctl_add != epoll_ctl_add
|
||||||
@ -244,11 +252,16 @@ fn epoll_ctl(
|
|||||||
|
|
||||||
if op == epoll_ctl_add || op == epoll_ctl_mod {
|
if op == epoll_ctl_add || op == epoll_ctl_mod {
|
||||||
// Read event bitmask and data from epoll_event passed by caller.
|
// Read event bitmask and data from epoll_event passed by caller.
|
||||||
let events = this.read_scalar(&this.project_field(&event, 0)?)?.to_u32()?;
|
let mut events = this.read_scalar(&this.project_field(&event, 0)?)?.to_u32()?;
|
||||||
let data = this.read_scalar(&this.project_field(&event, 1)?)?.to_u64()?;
|
let data = this.read_scalar(&this.project_field(&event, 1)?)?.to_u64()?;
|
||||||
|
|
||||||
// Unset the flag we support to discover if any unsupported flags are used.
|
// Unset the flag we support to discover if any unsupported flags are used.
|
||||||
let mut flags = events;
|
let mut flags = events;
|
||||||
|
// epoll_wait(2) will always wait for epollhup; it is not
|
||||||
|
// necessary to set it in events when calling epoll_ctl().
|
||||||
|
// So we will always set this event type.
|
||||||
|
events |= epollhup;
|
||||||
|
|
||||||
if events & epollet != epollet {
|
if events & epollet != epollet {
|
||||||
// We only support edge-triggered notification for now.
|
// We only support edge-triggered notification for now.
|
||||||
throw_unsup_format!("epoll_ctl: epollet flag must be included.");
|
throw_unsup_format!("epoll_ctl: epollet flag must be included.");
|
||||||
@ -264,6 +277,9 @@ fn epoll_ctl(
|
|||||||
if flags & epollrdhup == epollrdhup {
|
if flags & epollrdhup == epollrdhup {
|
||||||
flags &= !epollrdhup;
|
flags &= !epollrdhup;
|
||||||
}
|
}
|
||||||
|
if flags & epollhup == epollhup {
|
||||||
|
flags &= !epollhup;
|
||||||
|
}
|
||||||
if flags != 0 {
|
if flags != 0 {
|
||||||
throw_unsup_format!(
|
throw_unsup_format!(
|
||||||
"epoll_ctl: encountered unknown unsupported flags {:#x}",
|
"epoll_ctl: encountered unknown unsupported flags {:#x}",
|
||||||
|
@ -49,8 +49,8 @@ fn name(&self) -> &'static str {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
|
fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
|
||||||
// We only check the status of EPOLLIN, EPOLLOUT and EPOLLRDHUP flags. If other event flags
|
// We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags.
|
||||||
// need to be supported in the future, the check should be added here.
|
// If other event flags need to be supported in the future, the check should be added here.
|
||||||
|
|
||||||
let mut epoll_ready_events = EpollReadyEvents::new();
|
let mut epoll_ready_events = EpollReadyEvents::new();
|
||||||
|
|
||||||
@ -76,6 +76,7 @@ fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> {
|
|||||||
// for read and write.
|
// for read and write.
|
||||||
epoll_ready_events.epollin = true;
|
epoll_ready_events.epollin = true;
|
||||||
epoll_ready_events.epollout = true;
|
epoll_ready_events.epollout = true;
|
||||||
|
epoll_ready_events.epollhup = true;
|
||||||
}
|
}
|
||||||
Ok(epoll_ready_events)
|
Ok(epoll_ready_events)
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,8 @@ fn test_epoll_socketpair() {
|
|||||||
|
|
||||||
// Check result from epoll_wait.
|
// Check result from epoll_wait.
|
||||||
// We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer.
|
// We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer.
|
||||||
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
|
let expected_event =
|
||||||
|
u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP).unwrap();
|
||||||
let expected_value = u64::try_from(fds[1]).unwrap();
|
let expected_value = u64::try_from(fds[1]).unwrap();
|
||||||
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
|
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
|
||||||
}
|
}
|
||||||
@ -141,7 +142,8 @@ fn test_epoll_ctl_mod() {
|
|||||||
assert_eq!(res, 0);
|
assert_eq!(res, 0);
|
||||||
|
|
||||||
// Check result from epoll_wait.
|
// Check result from epoll_wait.
|
||||||
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
|
let expected_event =
|
||||||
|
u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLHUP).unwrap();
|
||||||
let expected_value = u64::try_from(fds[1]).unwrap();
|
let expected_value = u64::try_from(fds[1]).unwrap();
|
||||||
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
|
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user