fix(client): wait for the connection task to shut down cleanly before disconnecting and increase test timeout

This commit is contained in:
2026-03-30 00:03:46 +00:00
parent c97beed6e0
commit dbcfdb1fb6
4 changed files with 19 additions and 3 deletions

View File

@@ -1,5 +1,11 @@
# Changelog # Changelog
## 2026-03-30 - 1.10.2 - fix(client)
wait for the connection task to shut down cleanly before disconnecting and increase test timeout
- store the spawned client connection task handle and await it during disconnect with a 5 second timeout so the disconnect frame can be sent before closing
- increase the test script timeout from 60 seconds to 90 seconds to reduce flaky test runs
## 2026-03-29 - 1.10.1 - fix(test, docs, scripts) ## 2026-03-29 - 1.10.1 - fix(test, docs, scripts)
correct test command verbosity, shorten load test timings, and document forwarding modes correct test command verbosity, shorten load test timings, and document forwarding modes

View File

@@ -12,7 +12,7 @@
"scripts": { "scripts": {
"build": "(tsbuild tsfolders) && (tsrust)", "build": "(tsbuild tsfolders) && (tsrust)",
"test:before": "(tsrust)", "test:before": "(tsrust)",
"test": "tstest test/ --verbose --logfile --timeout 60", "test": "tstest test/ --verbose --logfile --timeout 90",
"buildDocs": "tsdoc" "buildDocs": "tsdoc"
}, },
"repository": { "repository": {

View File

@@ -81,6 +81,7 @@ pub struct VpnClient {
connected_since: Arc<RwLock<Option<std::time::Instant>>>, connected_since: Arc<RwLock<Option<std::time::Instant>>>,
quality_rx: Option<watch::Receiver<ConnectionQuality>>, quality_rx: Option<watch::Receiver<ConnectionQuality>>,
link_health: Arc<RwLock<LinkHealth>>, link_health: Arc<RwLock<LinkHealth>>,
connection_handle: Option<tokio::task::JoinHandle<()>>,
} }
impl VpnClient { impl VpnClient {
@@ -93,6 +94,7 @@ impl VpnClient {
connected_since: Arc::new(RwLock::new(None)), connected_since: Arc::new(RwLock::new(None)),
quality_rx: None, quality_rx: None,
link_health: Arc::new(RwLock::new(LinkHealth::Degraded)), link_health: Arc::new(RwLock::new(LinkHealth::Degraded)),
connection_handle: None,
} }
} }
@@ -280,7 +282,7 @@ impl VpnClient {
// Spawn packet forwarding loop // Spawn packet forwarding loop
let assigned_ip_clone = assigned_ip.clone(); let assigned_ip_clone = assigned_ip.clone();
tokio::spawn(client_loop( let join_handle = tokio::spawn(client_loop(
sink, sink,
stream, stream,
noise_transport, noise_transport,
@@ -294,6 +296,7 @@ impl VpnClient {
tun_writer, tun_writer,
tun_subnet, tun_subnet,
)); ));
self.connection_handle = Some(join_handle);
Ok(assigned_ip_clone) Ok(assigned_ip_clone)
} }
@@ -303,6 +306,13 @@ impl VpnClient {
if let Some(tx) = self.shutdown_tx.take() { if let Some(tx) = self.shutdown_tx.take() {
let _ = tx.send(()).await; let _ = tx.send(()).await;
} }
// Wait for the connection task to send the Disconnect frame and close
if let Some(handle) = self.connection_handle.take() {
let _ = tokio::time::timeout(
std::time::Duration::from_secs(5),
handle,
).await;
}
*self.assigned_ip.write().await = None; *self.assigned_ip.write().await = None;
*self.connected_since.write().await = None; *self.connected_since.write().await = None;
*self.state.write().await = ClientState::Disconnected; *self.state.write().await = ClientState::Disconnected;

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartvpn', name: '@push.rocks/smartvpn',
version: '1.10.1', version: '1.10.2',
description: 'A VPN solution with TypeScript control plane and Rust data plane daemon' description: 'A VPN solution with TypeScript control plane and Rust data plane daemon'
} }