diff --git a/Sources/FoundationNetworking/URLSession/URLSessionTask.swift b/Sources/FoundationNetworking/URLSession/URLSessionTask.swift index 38e126ed72..12a0fd40ef 100644 --- a/Sources/FoundationNetworking/URLSession/URLSessionTask.swift +++ b/Sources/FoundationNetworking/URLSession/URLSessionTask.swift @@ -364,11 +364,20 @@ open class URLSessionTask : NSObject, NSCopying { */ open func cancel() { workQueue.sync { - guard self.state == .running || self.state == .suspended else { return } - self.state = .canceling + let canceled = self.syncQ.sync { () -> Bool in + guard self._state == .running || self._state == .suspended else { return true } + self._state = .canceling + return false + } + guard !canceled else { return } self._getProtocol { (urlProtocol) in self.workQueue.async { - let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil)) + var info = [NSLocalizedDescriptionKey: "\(URLError.Code.cancelled)" as Any] + if let url = self.originalRequest?.url { + info[NSURLErrorFailingURLErrorKey] = url + info[NSURLErrorFailingURLStringErrorKey] = url.absoluteString + } + let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: info)) self.error = urlError if let urlProtocol = urlProtocol { urlProtocol.stopLoading() diff --git a/Tests/Foundation/Tests/TestURLSession.swift b/Tests/Foundation/Tests/TestURLSession.swift index 6f857a2c94..59922b28cb 100644 --- a/Tests/Foundation/Tests/TestURLSession.swift +++ b/Tests/Foundation/Tests/TestURLSession.swift @@ -1443,6 +1443,9 @@ class TestURLSession: LoopbackServerTest { XCTAssertNotNil(error as? URLError) if let urlError = error as? URLError { XCTAssertEqual(urlError._nsError.code, NSURLErrorCancelled) + XCTAssertEqual(urlError.userInfo[NSURLErrorFailingURLErrorKey] as? URL, URL(string: urlString)) + XCTAssertEqual(urlError.userInfo[NSURLErrorFailingURLStringErrorKey] as? String, urlString) + XCTAssertEqual(urlError.localizedDescription, "cancelled") } expect.fulfill()