Skip to content

Commit

Permalink
feat: Replace is_connect_failed with is_err
Browse files Browse the repository at this point in the history
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
  • Loading branch information
irvingoujAtDevolution authored Mar 21, 2024
1 parent 50454d1 commit e25b3b4
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 4 deletions.
2 changes: 1 addition & 1 deletion examples/tcp_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

Expand Down
7 changes: 6 additions & 1 deletion src/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 7 additions & 1 deletion src/iocp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions src/kqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
21 changes: 21 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 5 additions & 0 deletions src/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
7 changes: 6 additions & 1 deletion src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}

0 comments on commit e25b3b4

Please sign in to comment.