diff --git a/FlyingSocks/Sources/AsyncSocket.swift b/FlyingSocks/Sources/AsyncSocket.swift index 8d235e9..032096f 100644 --- a/FlyingSocks/Sources/AsyncSocket.swift +++ b/FlyingSocks/Sources/AsyncSocket.swift @@ -123,9 +123,14 @@ public struct AsyncSocket: Sendable { timeout: TimeInterval = 5) async throws -> Self { try await withThrowingTimeout(seconds: timeout) { let socket = try Socket(domain: Int32(type(of: address).family), type: .stream) - let asyncSocket = try AsyncSocket(socket: socket, pool: pool) - try await asyncSocket.connect(to: address) - return asyncSocket + do { + let asyncSocket = try AsyncSocket(socket: socket, pool: pool) + try await asyncSocket.connect(to: address) + return asyncSocket + } catch { + try? socket.close() + throw error + } } } @@ -134,7 +139,12 @@ public struct AsyncSocket: Sendable { try await pool.loopUntilReady(for: .connection, on: socket) { let file = try socket.accept().file let socket = Socket(file: file) - return try AsyncSocket(socket: socket, pool: pool) + do { + return try AsyncSocket(socket: socket, pool: pool) + } catch { + try? socket.close() + throw error + } } } diff --git a/FlyingSocks/Tests/AsyncSocketTests.swift b/FlyingSocks/Tests/AsyncSocketTests.swift index d8fe883..1237457 100644 --- a/FlyingSocks/Tests/AsyncSocketTests.swift +++ b/FlyingSocks/Tests/AsyncSocketTests.swift @@ -74,6 +74,16 @@ struct AsyncSocketTests { try await task.value } + @Test + func connected_ThrowsError_WhenConnectFails() async throws { + await #expect(throws: SocketError.self) { + _ = try await AsyncSocket.connected( + to: sockaddr_un.unix(path: "/nonexistent/\(UUID().uuidString)"), + pool: DisconnectedPool() + ) + } + } + @Test(.disabled("problematic test as file descriptor can be re-opened by another parallel test")) func socketReadByte_ThrowsDisconnected_WhenSocketIsClosed() async throws { let s1 = try await AsyncSocket.make()