From f1db1380647453ef03aa9814201a06378b798d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Qu=E1=BB=91c=20=C4=90=E1=BA=A1t?= Date: Thu, 21 May 2026 13:14:58 +0700 Subject: [PATCH] fix(connections): close SSH tunnel when a pending connection is cancelled (#1369) --- CHANGELOG.md | 1 + .../Core/Database/DatabaseManager+EnsureConnected.swift | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2681d6eb..7fbd84d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Reassigning the Execute Query, Execute All Statements, and Cancel Query shortcuts now takes effect, and the Query menu shows the new keys (#1357) - Custom shortcuts now require a modifier key, so a plain key like Space is no longer accepted and then silently ignored (#1357) - Cancelling a pending connection no longer lets the abandoned attempt overwrite or drop a later successful connection to the same database (#1358) +- Cancelling a pending SSH connection now closes its tunnel instead of leaving the local forward port open (#1369) - Importing connections from DBeaver now brings over the username (#1355) ## [0.43.1] - 2026-05-20 diff --git a/TablePro/Core/Database/DatabaseManager+EnsureConnected.swift b/TablePro/Core/Database/DatabaseManager+EnsureConnected.swift index fcdbaf506..c9437445c 100644 --- a/TablePro/Core/Database/DatabaseManager+EnsureConnected.swift +++ b/TablePro/Core/Database/DatabaseManager+EnsureConnected.swift @@ -4,6 +4,7 @@ // import Foundation +import os extension DatabaseManager { func ensureConnected(_ connection: DatabaseConnection) async throws { @@ -16,6 +17,13 @@ extension DatabaseManager { func cancelEnsureConnected(_ connectionId: UUID) async { await ensureConnectedDedup.cancel(key: connectionId) if let session = activeSessions[connectionId], session.driver == nil { + if session.connection.resolvedSSHConfig.enabled { + do { + try await SSHTunnelManager.shared.closeTunnel(connectionId: connectionId) + } catch { + Self.logger.warning("SSH tunnel cleanup failed for \(connectionId): \(error.localizedDescription)") + } + } removeSessionEntry(for: connectionId) if currentSessionId == connectionId { currentSessionId = nil