feat: Replace is_connect_failed with is_err

In linux, epoll, EPOLLHUP may happen even if no connection call is made. It
would confuse callers for what is actually happening.

Replaced is_connect_failed, and we detect if connection failed by using the
combination of is_err and is_interrupt, please see the example, tcp_client
This commit is contained in:
irvingouj @ Devolutions 2024-03-21 01:04:46 -04:00 committed by GitHub
parent 50454d1cea
commit e25b3b4e4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 51 additions and 4 deletions

View File

@ -28,7 +28,7 @@ fn main() -> io::Result<()> {
};
println!("event: {:?}", event);
if event.is_connect_failed().unwrap_or_default() {
if event.is_err().unwrap_or(false) {
println!("connect failed");
}

View File

@ -386,9 +386,14 @@ impl EventExtra {
pub fn is_connect_failed(&self) -> Option<bool> {
Some(
self.flags.contains(epoll::EventFlags::ERR)
|| self.flags.contains(epoll::EventFlags::HUP),
&& self.flags.contains(epoll::EventFlags::HUP),
)
}
#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.contains(epoll::EventFlags::ERR))
}
}
/// The notifier for Linux.

View File

@ -682,11 +682,17 @@ impl EventExtra {
self.flags.set(AfdPollMask::RECEIVE_EXPEDITED, active);
}
/// Check if TCP connect failed.
/// Check if TCP connect failed. Deprecated.
#[inline]
pub fn is_connect_failed(&self) -> Option<bool> {
Some(self.flags.intersects(AfdPollMask::CONNECT_FAIL))
}
/// Check if TCP connect failed.
#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.intersects(AfdPollMask::CONNECT_FAIL))
}
}
/// A packet used to wake up the poller with an event.

View File

@ -376,6 +376,11 @@ impl EventExtra {
pub fn is_connect_failed(&self) -> Option<bool> {
None
}
#[inline]
pub fn is_err(&self) -> Option<bool> {
None
}
}
pub(crate) fn mode_to_flags(mode: PollMode) -> kqueue::EventFlags {

View File

@ -392,10 +392,31 @@ impl Event {
/// Returns `Some(true)` if the connection has failed, `Some(false)` if the connection has not failed,
/// or `None` if the platform does not support detecting this condition.
#[inline]
#[deprecated(
since = "3.4.0",
note = "use `is_err` in combination of is_hup instead, see documentation for `is_err`"
)]
pub fn is_connect_failed(&self) -> Option<bool> {
self.extra.is_connect_failed()
}
/// Tells if this event is the result of a connection failure.
///
/// This function checks if an error exist,particularlly useful in detecting if TCP connection failed. It corresponds to the `EPOLLERR` event in Linux
/// and `CONNECT_FAILED` event in Windows IOCP.
///
/// ## Caveats
///
/// In `epoll`, a TCP connection failure is indicated by `EPOLLERR` + `EPOLLHUP`, though just `EPOLLERR` is enough to indicate a connection failure.
/// EPOLLHUP may happen when we haven't event called `connect` on the socket, but it is still a valid event to check for.
///
/// Returns `Some(true)` if the connection has failed, `Some(false)` if there is an error,
/// or `None` if the platform does not support detecting this condition.
#[inline]
pub fn is_err(&self) -> Option<bool> {
self.extra.is_err()
}
/// Remove any extra information from this event.
#[inline]
pub fn clear_extra(&mut self) {

View File

@ -435,6 +435,11 @@ impl EventExtra {
pub fn is_connect_failed(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR) || self.flags.contains(PollFlags::HUP))
}
#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR))
}
}
fn cvt_mode_as_remove(mode: PollMode) -> io::Result<bool> {

View File

@ -253,6 +253,11 @@ impl EventExtra {
#[inline]
pub fn is_connect_failed(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR) || self.flags.contains(PollFlags::HUP))
Some(self.flags.contains(PollFlags::ERR) && self.flags.contains(PollFlags::HUP))
}
#[inline]
pub fn is_err(&self) -> Option<bool> {
Some(self.flags.contains(PollFlags::ERR))
}
}