From 6ac9cdc2b5c38153a5faaf41ce8421b09aaf053e Mon Sep 17 00:00:00 2001 From: licunlong Date: Wed, 31 May 2023 11:20:33 +0800 Subject: [PATCH 8/9] fix: change the socket logic to keep the same as systemd 1. check the events number got from wait_for_events(), quick return when it is 0. 2. make flush_accept() return the error. 3. close the accepted fd instead port fd itself. --- coms/socket/src/mng.rs | 1 + coms/socket/src/port.rs | 54 ++++++++++++++++++++++++++--------------- core/lib/error.rs | 28 +++++++++++++++++++++ 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs index 0435827..da396de 100644 --- a/coms/socket/src/mng.rs +++ b/coms/socket/src/mng.rs @@ -597,6 +597,7 @@ impl SocketMng { if port.fd() < 0 { continue; } + let _ = port.flush_accept(); port.flush_fd(); } } diff --git a/coms/socket/src/port.rs b/coms/socket/src/port.rs index 870cb70..0500669 100644 --- a/coms/socket/src/port.rs +++ b/coms/socket/src/port.rs @@ -151,29 +151,43 @@ impl SocketPort { } } - pub(super) fn flush_accept(&self) { + pub(super) fn flush_accept(&self) -> Result<()> { if let Ok(true) = socket::getsockopt(self.fd(), sockopt::AcceptConn) { for _i in 1..1024 { - while let Err(e) = io_util::wait_for_events(self.fd(), PollFlags::POLLIN, 0) { - if let basic::Error::Nix { - source: Errno::EINTR, - } = e - { - continue; + let events = match io_util::wait_for_events(self.fd(), PollFlags::POLLIN, 0) { + Err(e) => { + if let basic::Error::Nix { + source: Errno::EINTR, + } = e + { + continue; + } + return Err(e.into()); } - return; + Ok(v) => v, + }; + if events == 0 { + return Ok(()); } - match socket::accept4(self.fd(), SockFlag::SOCK_NONBLOCK | SockFlag::SOCK_CLOEXEC) - .map(|_| fd_util::close(self.fd())) - { - Ok(_) => {} - Err(_e) => { - // todo!(): if e == Errno::EAGAIN { return; } - return; + let cfd = match socket::accept4( + self.fd(), + SockFlag::SOCK_NONBLOCK | SockFlag::SOCK_CLOEXEC, + ) { + Err(e) => { + if e == Errno::EAGAIN { + return Ok(()); + } + if error_is_accept_again(&e) { + continue; + } + return Err(e.into()); } - } + Ok(v) => v, + }; + fd_util::close(cfd); } } + Ok(()) } pub(super) fn flush_fd(&self) { @@ -356,7 +370,7 @@ mod tests { assert_ne!(port.fd(), SOCKET_INVALID_FD); assert_eq!(port.family(), AddressFamily::Inet); - port.flush_accept(); + assert!(port.flush_accept().is_ok()); port.flush_fd(); port.close(false); } @@ -387,7 +401,7 @@ mod tests { assert_ne!(port.fd(), SOCKET_INVALID_FD); assert_eq!(port.family(), AddressFamily::Unix); - port.flush_accept(); + assert!(port.flush_accept().is_ok()); port.flush_fd(); port.close(false); } @@ -424,7 +438,7 @@ mod tests { assert_ne!(port.fd(), SOCKET_INVALID_FD); assert_eq!(port.family(), AddressFamily::Netlink); - port.flush_accept(); + assert!(port.flush_accept().is_ok()); port.flush_fd(); port.close(false); } @@ -519,7 +533,7 @@ mod tests { } // Rosource reclaim - port.flush_accept(); + assert!(port.flush_accept().is_ok()); port.flush_fd(); port.close(false); } diff --git a/core/lib/error.rs b/core/lib/error.rs index 100eb3c..331f367 100644 --- a/core/lib/error.rs +++ b/core/lib/error.rs @@ -289,3 +289,31 @@ impl From for Error { /// new Result pub type Result = std::result::Result; + +pub fn error_is_disconnect(e: &Errno) -> bool { + [ + Errno::ECONNABORTED, + Errno::ECONNREFUSED, + Errno::ECONNRESET, + Errno::EHOSTDOWN, + Errno::EHOSTUNREACH, + Errno::ENETDOWN, + Errno::ENETRESET, + Errno::ENONET, + Errno::ENOPROTOOPT, + Errno::ENOTCONN, + Errno::EPIPE, + Errno::EPROTO, + Errno::ESHUTDOWN, + Errno::ETIMEDOUT, + ] + .contains(e) +} + +pub fn error_is_transient(e: &Errno) -> bool { + [Errno::EAGAIN, Errno::EINTR].contains(e) +} + +pub fn error_is_accept_again(e: &Errno) -> bool { + error_is_disconnect(e) || error_is_transient(e) || e == &Errno::EOPNOTSUPP +} -- 2.30.2