Skip to content

Commit e3181ee

Browse files
weissiphausler
authored andcommitted
fix URLSession delegate ownership (#1098)
1 parent 6d107c1 commit e3181ee

File tree

1 file changed

+30
-17
lines changed

1 file changed

+30
-17
lines changed

Foundation/NSURLSession/http/EasyHandle.swift

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import Dispatch
5252
/// `Dispatch` only -- it is intentionally **not** thread safe.
5353
internal final class _EasyHandle {
5454
let rawHandle = CFURLSessionEasyHandleInit()
55-
unowned let delegate: _EasyHandleDelegate
55+
weak var delegate: _EasyHandleDelegate?
5656
fileprivate var headerList: _CurlStringList?
5757
fileprivate var pauseState: _PauseState = []
5858
internal var fileLength: Int64 = 0
@@ -88,7 +88,7 @@ extension _EasyHandle {
8888

8989
internal extension _EasyHandle {
9090
func completedTransfer(withErrorCode errorCode: Int?) {
91-
delegate.transferCompleted(withErrorCode: errorCode)
91+
delegate?.transferCompleted(withErrorCode: errorCode)
9292
}
9393
}
9494
internal protocol _EasyHandleDelegate: class {
@@ -479,12 +479,15 @@ fileprivate extension _EasyHandle {
479479
func didReceive(data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int) -> Int {
480480
let d: Int = {
481481
let buffer = Data(bytes: data, count: size*nmemb)
482-
switch delegate.didReceive(data: buffer) {
483-
case .proceed: return size * nmemb
484-
case .abort: return 0
485-
case .pause:
482+
switch delegate?.didReceive(data: buffer) {
483+
case .some(.proceed): return size * nmemb
484+
case .some(.abort): return 0
485+
case .some(.pause):
486486
pauseState.insert(.receivePaused)
487487
return Int(CFURLSessionWriteFuncPause)
488+
case .none:
489+
/* the delegate disappeared */
490+
return 0
488491
}
489492
}()
490493
return d
@@ -497,12 +500,15 @@ fileprivate extension _EasyHandle {
497500
self.fileLength = Int64(fileLength)
498501
let d: Int = {
499502
let buffer = Data(bytes: data, count: size*nmemb)
500-
switch delegate.didReceive(headerData: buffer) {
501-
case .proceed: return size * nmemb
502-
case .abort: return 0
503-
case .pause:
503+
switch delegate?.didReceive(headerData: buffer) {
504+
case .some(.proceed): return size * nmemb
505+
case .some(.abort): return 0
506+
case .some(.pause):
504507
pauseState.insert(.receivePaused)
505508
return Int(CFURLSessionWriteFuncPause)
509+
case .none:
510+
/* the delegate disappeared */
511+
return 0
506512
}
507513
}()
508514
return d
@@ -514,14 +520,17 @@ fileprivate extension _EasyHandle {
514520
func fill(writeBuffer data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int) -> Int {
515521
let d: Int = {
516522
let buffer = UnsafeMutableBufferPointer(start: data, count: size * nmemb)
517-
switch delegate.fill(writeBuffer: buffer) {
518-
case .pause:
523+
switch delegate?.fill(writeBuffer: buffer) {
524+
case .some(.pause):
519525
pauseState.insert(.sendPaused)
520526
return Int(CFURLSessionReadFuncPause)
521-
case .abort:
527+
case .some(.abort):
522528
return Int(CFURLSessionReadFuncAbort)
523-
case .bytes(let length):
529+
case .some(.bytes(let length)):
524530
return length
531+
case .none:
532+
/* the delegate disappeared */
533+
return Int(CFURLSessionReadFuncAbort)
525534
}
526535
}()
527536
return d
@@ -541,16 +550,20 @@ fileprivate extension _EasyHandle {
541550
// <https://en.wikipedia.org/wiki/Quality_of_service>
542551
}
543552
func updateProgressMeter(with propgress: _Progress) {
544-
delegate.updateProgressMeter(with: propgress)
553+
delegate?.updateProgressMeter(with: propgress)
545554
}
546555

547556
func seekInputStream(offset: Int64, origin: CInt) -> CInt {
548557
let d: Int32 = {
549558
/// libcurl should only use SEEK_SET
550559
guard origin == SEEK_SET else { fatalError("Unexpected 'origin' in seek.") }
551560
do {
552-
try delegate.seekInputStream(to: UInt64(offset))
553-
return CFURLSessionSeekOk
561+
if let delegate = delegate {
562+
try delegate.seekInputStream(to: UInt64(offset))
563+
return CFURLSessionSeekOk
564+
} else {
565+
return CFURLSessionSeekCantSeek
566+
}
554567
} catch {
555568
return CFURLSessionSeekCantSeek
556569
}

0 commit comments

Comments
 (0)