From 3a8c6c71828b3f018eb17dd25ad82d97d9544826 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 8 Jan 2025 15:11:01 +0100 Subject: [PATCH] chore(connlib): assert that we don't emit `WouldBlock` errors (#7696) When file descriptors like sockets or the TUN device are opened in non-blocking mode, performing operations that would block emit the `WouldBlock` IO error. These errors _should_ be translated into `Poll::Pending` and have a waker registered that gets called whenever the operation should be attempted again. Therefore, we should _never_ see these IO errors. Previously, the implementation of the tunnel's event-loop did not yet properly handle this backpressure and instead sometimes dropped packets when it should have suspended. This has since been fixed but the then introduced branch of just ignored the `io::ErrorKind::WouldBlock` errors had remained. Changing this to a debug-assert will alert us whenever we accidentally break this without altering the behaviour of the release binary. --- rust/connlib/clients/shared/src/eventloop.rs | 8 +++++--- rust/gateway/src/eventloop.rs | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/rust/connlib/clients/shared/src/eventloop.rs b/rust/connlib/clients/shared/src/eventloop.rs index c67a340af..378c660fd 100644 --- a/rust/connlib/clients/shared/src/eventloop.rs +++ b/rust/connlib/clients/shared/src/eventloop.rs @@ -89,9 +89,6 @@ where self.handle_tunnel_event(event); continue; } - Poll::Ready(Err(e)) if e.kind() == io::ErrorKind::WouldBlock => { - continue; - } Poll::Ready(Err(e)) if e.kind() == io::ErrorKind::NetworkUnreachable || e.kind() == io::ErrorKind::HostUnreachable => @@ -100,6 +97,11 @@ where continue; } Poll::Ready(Err(e)) => { + debug_assert_ne!( + e.kind(), + io::ErrorKind::WouldBlock, + "Tunnel should never emit WouldBlock errors but suspend instead" + ); telemetry_event!("Tunnel error: {}", err_with_src(&e)); continue; } diff --git a/rust/gateway/src/eventloop.rs b/rust/gateway/src/eventloop.rs index 67216120b..ec0c04ab4 100644 --- a/rust/gateway/src/eventloop.rs +++ b/rust/gateway/src/eventloop.rs @@ -77,9 +77,6 @@ impl Eventloop { self.handle_tunnel_event(event); continue; } - Poll::Ready(Err(e)) if e.kind() == io::ErrorKind::WouldBlock => { - continue; - } Poll::Ready(Err(e)) if e.kind() == io::ErrorKind::NetworkUnreachable || e.kind() == io::ErrorKind::HostUnreachable => @@ -88,6 +85,12 @@ impl Eventloop { continue; } Poll::Ready(Err(e)) => { + debug_assert_ne!( + e.kind(), + io::ErrorKind::WouldBlock, + "Tunnel should never emit WouldBlock errors but suspend instead" + ); + let e = anyhow::Error::from(e); if e.root_cause().is::() {