Skip to content

Commit 38bff22

Browse files
authored
Merge branch 'master' into master
2 parents 413c913 + 41542b2 commit 38bff22

File tree

8 files changed

+54
-18
lines changed

8 files changed

+54
-18
lines changed

Foundation/NSKeyedArchiver.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,13 @@ open class NSKeyedArchiver : NSCoder {
159159
return false
160160
}
161161

162+
defer { CFWriteStreamClose(writeStream) }
163+
162164
let keyedArchiver = NSKeyedArchiver(output: writeStream)
163165

164166
keyedArchiver.encode(rootObject, forKey: NSKeyedArchiveRootObjectKey)
165167
keyedArchiver.finishEncoding()
166168
finishedEncoding = keyedArchiver._flags.contains(ArchiverFlags.finishedEncoding)
167-
168-
CFWriteStreamClose(writeStream)
169169

170170
return finishedEncoding
171171
}

Foundation/NSKeyedUnarchiver.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ open class NSKeyedUnarchiver : NSCoder {
7474
return nil
7575
}
7676

77+
defer { CFReadStreamClose(readStream) }
78+
7779
let keyedUnarchiver = NSKeyedUnarchiver(stream: Stream.stream(readStream))
7880
do {
7981
try root = keyedUnarchiver.decodeTopLevelObject(forKey: NSKeyedArchiveRootObjectKey)
8082
keyedUnarchiver.finishDecoding()
8183
} catch {
8284
}
8385

84-
CFReadStreamClose(readStream)
85-
8686
return root
8787
}
8888

Foundation/NSURLSession/EasyHandle.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ internal final class _EasyHandle {
5656
fileprivate var headerList: _CurlStringList?
5757
fileprivate var pauseState: _PauseState = []
5858
internal var fileLength: Int64 = 0
59+
internal var timeoutTimer: _TimeoutSource!
60+
5961
init(delegate: _EasyHandleDelegate) {
6062
self.delegate = delegate
6163
setupCallbacks()
@@ -387,31 +389,47 @@ fileprivate extension _EasyHandle {
387389
}
388390

389391
fileprivate extension _EasyHandle {
392+
393+
func resetTimer() {
394+
//simply create a new timer with the same queue, timeout and handler
395+
//this must cancel the old handler and reset the timer
396+
timeoutTimer = _TimeoutSource(queue: timeoutTimer.queue, milliseconds: timeoutTimer.milliseconds, handler: timeoutTimer.handler)
397+
}
398+
390399
/// Forward the libcurl callbacks into Swift methods
391400
func setupCallbacks() {
392401
// write
393402
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionWRITEDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
394403

395404
try! CFURLSession_easy_setopt_wc(rawHandle, CFURLSessionOptionWRITEFUNCTION) { (data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, userdata: UnsafeMutableRawPointer?) -> Int in
396405
guard let handle = _EasyHandle.from(callbackUserData: userdata) else { return 0 }
406+
defer {
407+
handle.resetTimer()
408+
}
397409
return handle.didReceive(data: data, size: size, nmemb: nmemb)
398-
}.asError()
410+
}.asError()
399411

400412
// read
401413
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionREADDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
402414
try! CFURLSession_easy_setopt_wc(rawHandle, CFURLSessionOptionREADFUNCTION) { (data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, userdata: UnsafeMutableRawPointer?) -> Int in
403415
guard let handle = _EasyHandle.from(callbackUserData: userdata) else { return 0 }
416+
defer {
417+
handle.resetTimer()
418+
}
404419
return handle.fill(writeBuffer: data, size: size, nmemb: nmemb)
405-
}.asError()
420+
}.asError()
406421

407422
// header
408423
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionHEADERDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
409424
try! CFURLSession_easy_setopt_wc(rawHandle, CFURLSessionOptionHEADERFUNCTION) { (data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, userdata: UnsafeMutableRawPointer?) -> Int in
410425
guard let handle = _EasyHandle.from(callbackUserData: userdata) else { return 0 }
426+
defer {
427+
handle.resetTimer()
428+
}
411429
var length = Double()
412430
try! CFURLSession_easy_getinfo_double(handle.rawHandle, CFURLSessionInfoCONTENT_LENGTH_DOWNLOAD, &length).asError()
413431
return handle.didReceive(headerData: data, size: size, nmemb: nmemb, fileLength: length)
414-
}.asError()
432+
}.asError()
415433

416434
// socket options
417435
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSOCKOPTDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
@@ -424,7 +442,7 @@ fileprivate extension _EasyHandle {
424442
} catch {
425443
return 1
426444
}
427-
}.asError()
445+
}.asError()
428446
// seeking in input stream
429447
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSEEKDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
430448
try! CFURLSession_easy_setopt_seek(rawHandle, CFURLSessionOptionSEEKFUNCTION, { (userdata, offset, origin) -> Int32 in

Foundation/NSURLSession/MultiHandle.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,15 @@ fileprivate extension URLSession._MultiHandle._SocketRegisterAction {
300300

301301
/// A helper class that wraps a libdispatch timer.
302302
///
303-
/// Used to implement the timeout of `URLSession.MultiHandle`.
304-
fileprivate class _TimeoutSource {
303+
/// Used to implement the timeout of `URLSession.MultiHandle` and `URLSession.EasyHandle`
304+
class _TimeoutSource {
305305
let rawSource: DispatchSource
306306
let milliseconds: Int
307+
let queue: DispatchQueue //needed to restart the timer for EasyHandles
308+
let handler: DispatchWorkItem //needed to restart the timer for EasyHandles
307309
init(queue: DispatchQueue, milliseconds: Int, handler: DispatchWorkItem) {
310+
self.queue = queue
311+
self.handler = handler
308312
self.milliseconds = milliseconds
309313
self.rawSource = DispatchSource.makeTimerSource(queue: queue) as! DispatchSource
310314

Foundation/NSURLSession/NSURLSessionTask.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,14 @@ fileprivate extension URLSessionTask {
571571
//set the request timeout
572572
//TODO: the timeout value needs to be reset on every data transfer
573573
let s = session as! URLSession
574-
easyHandle.set(timeout: Int(s.configuration.timeoutIntervalForRequest))
574+
let timeoutInterval = Int(s.configuration.timeoutIntervalForRequest) * 1000
575+
let timeoutHandler = DispatchWorkItem { [weak self] in
576+
guard let currentTask = self else { fatalError("Timeout on a task that doesn't exist") } //this guard must always pass
577+
currentTask.internalState = .transferFailed
578+
let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorTimedOut, userInfo: nil))
579+
currentTask.completeTask(withError: urlError)
580+
}
581+
easyHandle.timeoutTimer = _TimeoutSource(queue: workQueue, milliseconds: timeoutInterval, handler: timeoutHandler)
575582

576583
easyHandle.set(automaticBodyDecompression: true)
577584
easyHandle.set(requestMethod: request.httpMethod ?? "GET")
@@ -830,6 +837,9 @@ extension URLSessionTask {
830837
}
831838
self.response = response
832839

840+
//We don't want a timeout to be triggered after this. The timeout timer needs to be cancelled.
841+
easyHandle.timeoutTimer = nil
842+
833843
//because we deregister the task with the session on internalState being set to taskCompleted
834844
//we need to do the latter after the delegate/handler was notified/invoked
835845
switch session.behaviour(for: self) {
@@ -881,6 +891,10 @@ extension URLSessionTask {
881891
guard case .transferFailed = internalState else {
882892
fatalError("Trying to complete the task, but its transfer isn't complete / failed.")
883893
}
894+
895+
//We don't want a timeout to be triggered after this. The timeout timer needs to be cancelled.
896+
easyHandle.timeoutTimer = nil
897+
884898
switch session.behaviour(for: self) {
885899
case .taskDelegate(let delegate):
886900
guard let s = session as? URLSession else { fatalError() }

Foundation/NSXMLParser.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,12 @@ open class XMLParser : NSObject {
559559
internal func parseFromStream() -> Bool {
560560
var result = true
561561
XMLParser.setCurrentParser(self)
562+
defer { XMLParser.setCurrentParser(nil) }
562563
if let stream = _stream {
563564
stream.open()
565+
defer { stream.close() }
564566
let buffer = malloc(_chunkSize)!.bindMemory(to: UInt8.self, capacity: _chunkSize)
567+
defer { free(buffer) }
565568
var len = stream.read(buffer, maxLength: _chunkSize)
566569
if len != -1 {
567570
while len > 0 {
@@ -572,10 +575,9 @@ open class XMLParser : NSObject {
572575
} else {
573576
result = false
574577
}
575-
free(buffer)
576-
stream.close()
577578
} else if let data = _data {
578579
let buffer = malloc(_chunkSize)!.bindMemory(to: UInt8.self, capacity: _chunkSize)
580+
defer { free(buffer) }
579581
var range = NSMakeRange(0, min(_chunkSize, data.count))
580582
while result {
581583
let chunk = data.withUnsafeBytes { (buffer: UnsafePointer<UInt8>) -> Data in
@@ -588,11 +590,9 @@ open class XMLParser : NSObject {
588590
}
589591
range = NSMakeRange(range.location + range.length, min(_chunkSize, data.count - (range.location + range.length)))
590592
}
591-
free(buffer)
592593
} else {
593594
result = false
594595
}
595-
XMLParser.setCurrentParser(nil)
596596
return result
597597
}
598598

TestFoundation/HTTPServer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class _TCPSocket {
7777
return sockaddr_in(sin_len: 0, sin_family: sa_family_t(AF_INET), sin_port: CFSwapInt16HostToBig(port), sin_addr: in_addr(s_addr: INADDR_ANY), sin_zero: (0,0,0,0,0,0,0,0) )
7878
#endif
7979
}
80+
8081
func acceptConnection(notify: ServerSemaphore) throws {
8182
_ = try attempt("listen", valid: isZero, listen(listenSocket, SOMAXCONN))
8283
try socketAddress.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout<sockaddr>.size, {
@@ -112,7 +113,6 @@ class _TCPSocket {
112113
for item in texts {
113114
sleep(UInt32(sendDelay))
114115
var bytes = Array(item.utf8)
115-
print(item)
116116
_ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, bytes.count)))
117117
}
118118
} else {
@@ -160,7 +160,7 @@ class _HTTPServer {
160160
} else {
161161
deadlineTime = .now()
162162
}
163-
163+
164164
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
165165
do {
166166
try self.socket.writeData(header: response.header, body: response.body, sendDelay: sendDelay, bodyChunks: bodyChunks)

TestFoundation/TestNSURLSession.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class TestURLSession : XCTestCase {
4848
try test.readAndRespond()
4949
test.stop()
5050
} catch let e as ServerError {
51-
if e.operation != "bind" { continue }
51+
if e.operation == "bind" { continue }
5252
throw e
5353
}
5454
}

0 commit comments

Comments
 (0)