From df78397870284f1de5dd90a51b2a70bb450240e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Sun, 15 Mar 2026 12:10:53 +0100 Subject: [PATCH] fix stale IMAP connection: clean up old connection on reconnect, robust disconnect - connect() now cleans up any stale connection/event loop group before creating a new one, preventing leaked resources after failed syncs - disconnect() uses try? for both channel close and group shutdown so "Already closed" errors don't prevent cleanup Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Sources/IMAPClient/IMAPClient.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPClient.swift b/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPClient.swift index 260df32..97f49f6 100644 --- a/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPClient.swift +++ b/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPClient.swift @@ -20,6 +20,14 @@ public actor IMAPClient: IMAPClientProtocol { // MARK: - Connection lifecycle public func connect() async throws { + // Clean up any stale connection from a previous failed sync + if connection != nil { + try? await connection?.disconnect() + try? await connection?.shutdown() + connection = nil + runner = nil + } + let conn = IMAPConnection(host: host, port: port) try await conn.connect() connection = conn @@ -36,8 +44,8 @@ public actor IMAPClient: IMAPClientProtocol { _ = try? await r.run(.logout) runner = r } - try await connection?.disconnect() - try await connection?.shutdown() + try? await connection?.disconnect() + try? await connection?.shutdown() connection = nil runner = nil }