-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Cancel DispatchSource
before closing socket (#4791)
#4859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,7 +99,7 @@ class _TCPSocket: CustomStringConvertible { | |
listening = false | ||
} | ||
|
||
init(port: UInt16?) throws { | ||
init(port: UInt16?, backlog: Int32) throws { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you choose Int32 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I propagated There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the explanation 🙌 No for me Int32 is the good choice, I asked only for know how did you make your choice. |
||
listening = true | ||
self.port = 0 | ||
|
||
|
@@ -124,7 +124,7 @@ class _TCPSocket: CustomStringConvertible { | |
try socketAddress.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout<sockaddr>.size, { | ||
let addr = UnsafePointer<sockaddr>($0) | ||
_ = try attempt("bind", valid: isZero, bind(_socket, addr, socklen_t(MemoryLayout<sockaddr>.size))) | ||
_ = try attempt("listen", valid: isZero, listen(_socket, SOMAXCONN)) | ||
_ = try attempt("listen", valid: isZero, listen(_socket, backlog)) | ||
}) | ||
|
||
var actualSA = sockaddr_in() | ||
|
@@ -295,8 +295,8 @@ class _HTTPServer: CustomStringConvertible { | |
let tcpSocket: _TCPSocket | ||
var port: UInt16 { tcpSocket.port } | ||
|
||
init(port: UInt16?) throws { | ||
tcpSocket = try _TCPSocket(port: port) | ||
init(port: UInt16?, backlog: Int32 = SOMAXCONN) throws { | ||
tcpSocket = try _TCPSocket(port: port, backlog: backlog) | ||
} | ||
|
||
init(socket: _TCPSocket) { | ||
|
@@ -1094,15 +1094,32 @@ enum InternalServerError : Error { | |
case badHeaders | ||
} | ||
|
||
extension LoopbackServerTest { | ||
struct Options { | ||
var serverBacklog: Int32 | ||
var isAsynchronous: Bool | ||
|
||
static let `default` = Options(serverBacklog: SOMAXCONN, isAsynchronous: true) | ||
} | ||
} | ||
|
||
class LoopbackServerTest : XCTestCase { | ||
private static let staticSyncQ = DispatchQueue(label: "org.swift.TestFoundation.HTTPServer.StaticSyncQ") | ||
|
||
private static var _serverPort: Int = -1 | ||
private static var _serverActive = false | ||
private static var testServer: _HTTPServer? = nil | ||
|
||
|
||
private static var _options: Options = .default | ||
|
||
static var options: Options { | ||
get { | ||
return staticSyncQ.sync { _options } | ||
} | ||
set { | ||
staticSyncQ.sync { _options = newValue } | ||
} | ||
} | ||
|
||
static var serverPort: Int { | ||
get { | ||
return staticSyncQ.sync { _serverPort } | ||
|
@@ -1119,27 +1136,42 @@ class LoopbackServerTest : XCTestCase { | |
|
||
override class func setUp() { | ||
super.setUp() | ||
Self.startServer() | ||
} | ||
|
||
override class func tearDown() { | ||
Self.stopServer() | ||
super.tearDown() | ||
} | ||
|
||
static func startServer() { | ||
var _serverPort = 0 | ||
let dispatchGroup = DispatchGroup() | ||
|
||
func runServer() throws { | ||
testServer = try _HTTPServer(port: nil) | ||
testServer = try _HTTPServer(port: nil, backlog: options.serverBacklog) | ||
_serverPort = Int(testServer!.port) | ||
serverActive = true | ||
dispatchGroup.leave() | ||
|
||
while serverActive { | ||
do { | ||
let httpServer = try testServer!.listen() | ||
globalDispatchQueue.async { | ||
|
||
func handleRequest() { | ||
let subServer = TestURLSessionServer(httpServer: httpServer) | ||
do { | ||
try subServer.readAndRespond() | ||
} catch { | ||
NSLog("readAndRespond: \(error)") | ||
} | ||
} | ||
|
||
if options.isAsynchronous { | ||
globalDispatchQueue.async(execute: handleRequest) | ||
} else { | ||
handleRequest() | ||
} | ||
} catch { | ||
if (serverActive) { // Ignore errors thrown on shutdown | ||
NSLog("httpServer: \(error)") | ||
|
@@ -1165,11 +1197,11 @@ class LoopbackServerTest : XCTestCase { | |
fatalError("Timedout waiting for server to be ready") | ||
} | ||
serverPort = _serverPort | ||
debugLog("Listening on \(serverPort)") | ||
} | ||
|
||
override class func tearDown() { | ||
static func stopServer() { | ||
serverActive = false | ||
try? testServer?.stop() | ||
super.tearDown() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it has to be done or one issue will be created ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't really say on behalf on this comment author😞 This was here from the beginning. Guess it is better to leave as is to keep the diff less noisy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let the Todo, I thought you've added it