From 30816dc6277de95045c8f1395aa91b1e7cc84344 Mon Sep 17 00:00:00 2001 From: kkocdko Date: Sun, 26 Apr 2026 19:03:17 +0800 Subject: [PATCH 1/4] Close transport on broker server disconnect --- src/client/mod.rs | 4 ++++ tests/integration/connect_options.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/client/mod.rs b/src/client/mod.rs index b084e80..321975d 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1598,6 +1598,10 @@ impl< .recv_body::>(&header) .await?; + // The server initiated the disconnect. We must close the transport on our side + // as well so that subsequent error handling (e.g. `abort`) sees a non-Ok network state. + self.raw.close_with(None); + return Err(MqttError::Disconnect { reason: disconnect.reason_code, reason_string: disconnect.reason_string.map(Property::into_inner), diff --git a/tests/integration/connect_options.rs b/tests/integration/connect_options.rs index 58352ca..2fe6a75 100644 --- a/tests/integration/connect_options.rs +++ b/tests/integration/connect_options.rs @@ -595,6 +595,9 @@ async fn keep_alive_not_kept_alive_idle_network() { server_reference: _, } | MqttError::Network(_) )); + + // A non-recoverable poll error should always allow calling abort without panicking. + c.abort().await; } #[tokio::test] From 3ac369f9acf355bf45df2f1efb532c0088b3a46d Mon Sep 17 00:00:00 2001 From: Julian Graf Date: Tue, 28 Apr 2026 10:45:25 +0200 Subject: [PATCH 2/4] fix integration test with hive --- tests/integration/connect_options.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/integration/connect_options.rs b/tests/integration/connect_options.rs index 2fe6a75..0dc8e34 100644 --- a/tests/integration/connect_options.rs +++ b/tests/integration/connect_options.rs @@ -638,11 +638,15 @@ async fn keep_alive_not_kept_alive_incoming_qos0() { assert_ok!( timeout(Duration::from_secs(4), async { - loop { - if let Err(MqttError::Network(_)) = rx.poll().await { - break; - } - } + while !matches!( + rx.poll().await, + Err(MqttError::Disconnect { + reason: ReasonCode::KeepAliveTimeout, + reason_string: _, + user_properties: _, + server_reference: _, + }) | Err(MqttError::Network(_)) + ) {} }) .await, "expected to be disconnected" From b6da07ef2e1b8f17bb8a44c80cfa4d06149d28c9 Mon Sep 17 00:00:00 2001 From: Julian Graf Date: Tue, 28 Apr 2026 10:49:25 +0200 Subject: [PATCH 3/4] add Client::abort to other failing integration tests --- tests/integration/connect_options.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration/connect_options.rs b/tests/integration/connect_options.rs index 0dc8e34..42b18de 100644 --- a/tests/integration/connect_options.rs +++ b/tests/integration/connect_options.rs @@ -651,6 +651,8 @@ async fn keep_alive_not_kept_alive_incoming_qos0() { .await, "expected to be disconnected" ); + // A non-recoverable poll error should always allow calling abort without panicking. + rx.abort().await; }; join!(receiver, publisher); @@ -702,6 +704,8 @@ async fn keep_alive_not_kept_alive_will_timing() { server_reference: _, } | MqttError::Network(_) )); + // A non-recoverable poll error should always allow calling abort without panicking. + tx.abort().await; disconnect(&mut rx, DEFAULT_DC_OPTIONS).await; } From 3b1c5b1843dc9f80a1bcfd7658a8f62713c04de0 Mon Sep 17 00:00:00 2001 From: Julian Graf Date: Tue, 28 Apr 2026 10:56:24 +0200 Subject: [PATCH 4/4] document change --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa5187..8225d8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add request problem information support - Add reason string to incoming PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK - Detect protocol error when server sends user properties (only when `MAX_USER_PROPERTIES` > 0) or a reason string in the PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK and UNSUBACK packets +- Fix client not dropping network connection on receival of a DISCONNECT packet leading to a panic on subsequent call to `Client::abort` in debug builds ## 0.5.1 - 2026-04-10