Skip to content

Commit a778166

Browse files
authored
Merge pull request #150 from gwynne/throw-socket-closed-error
Throw better errors for closed sockets
2 parents 5e59c09 + 4bce7fa commit a778166

File tree

3 files changed

+42
-13
lines changed

3 files changed

+42
-13
lines changed

Sources/Sockets/TCP/TCPReadableSocket.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ extension TCPReadableSocket {
2020
case EAGAIN:
2121
// timeout reached (linux)
2222
return 0
23+
case EBADF:
24+
// socket is (probably) already closed
25+
if isClosed {
26+
throw SocketsError(.socketIsClosed)
27+
} else {
28+
throw SocketsError(.readFailed)
29+
}
2330
default:
2431
throw SocketsError(.readFailed)
2532
}

Sources/Sockets/TCP/TCPWriteableSocket.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ extension TCPWriteableSocket {
1717
// itself throws an error.
1818
_ = try self.close()
1919
return 0
20+
case EBADF:
21+
// socket is (probably) already closed
22+
if isClosed {
23+
throw SocketsError(.socketIsClosed)
24+
} else {
25+
throw SocketsError(.writeFailed)
26+
}
2027
default:
2128
throw SocketsError(.writeFailed)
2229
}

Tests/SocketsTests/StreamTests.swift

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class StreamTests: XCTestCase {
1010
("testTCPInternetSocket", testTCPInternetSocket),
1111
("testDirect", testDirect),
1212
("testTCPInternetSocketThrows", testTCPInternetSocketThrows),
13+
("testTCPInternetSocketThrowsClosedError", testTCPInternetSocketThrowsClosedError),
1314
("testTCPServer", testTCPServer),
1415
]
1516

@@ -56,20 +57,34 @@ class StreamTests: XCTestCase {
5657
hostname: "google.com",
5758
port: 80
5859
)
59-
60-
do {
61-
_ = try google.write("GET /\r\n\r\n".makeBytes())
62-
XCTFail("should throw -- not connected")
63-
} catch {
64-
// pass
65-
}
66-
67-
do {
68-
_ = try google.read(max: 2048)
69-
XCTFail("should throw -- not connected")
70-
} catch {
71-
// pass
60+
61+
XCTAssertThrowsError(_ = try google.write("GET /\r\n\r\n".makeBytes()), "should throw -- not connected")
62+
XCTAssertThrowsError(_ = try google.read(max: 2048), "should throw -- not connected")
63+
}
64+
65+
func testTCPInternetSocketThrowsClosedError() throws {
66+
let httpBin = try TCPInternetSocket(
67+
scheme: "http",
68+
hostname: "httpbin.org",
69+
port: 80
70+
)
71+
try httpBin.setTimeout(10)
72+
try httpBin.connect()
73+
try httpBin.close()
74+
75+
let errorCheck = { (error: Error) -> Void in
76+
guard let socketError = error as? SocketsError else {
77+
XCTFail("thrown error must be a SocketsError")
78+
return
79+
}
80+
guard case .socketIsClosed = socketError.type else {
81+
XCTFail("thrown error must be specifically a .socketIsClosed error")
82+
return
83+
}
7284
}
85+
86+
XCTAssertThrowsError(_ = try httpBin.write("GET /\r\n\r\n"), "should throw -- not connected", errorCheck)
87+
XCTAssertThrowsError(_ = try httpBin.read(max: 2048), "should throw -- not connected", errorCheck)
7388
}
7489

7590

0 commit comments

Comments
 (0)