-
-
Notifications
You must be signed in to change notification settings - Fork 316
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
Crash accessing URLSessionTask.currentRequest
and URLRequest.allHTTPHeaderFields
#268
Comments
Thanks for reporting it!
I think that makes sense, yes. |
👋 Hi, 🐶 Datadog here. To add more context, the fix with capturing ImmutableRequest didn't seem to mute this problem entirely and we still got new reports. Ultimately we decided to avoid using Not sure how |
Hey, thanks for providing context, Maciek. Yeah, I kind of need to read |
I switched to using a Because Alamofire only accepts an Alamofire class PulseSessionDelegate: SessionDelegate {
let logger: NetworkLogger
init(logger: NetworkLogger) {
self.logger = logger
super.init()
}
// MARK: URLSessionTaskDelegate
func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) {
logger.logTaskCreated(task)
}
override func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
logger.logTask(task, didCompleteWithError: error)
super.urlSession(session, task: task, didCompleteWithError: error)
}
override func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
logger.logTask(task, didFinishCollecting: metrics)
super.urlSession(session, task: task, didFinishCollecting: metrics)
}
override func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
if task is URLSessionUploadTask {
logger.logTask(task, didUpdateProgress: (completed: totalBytesSent, total: totalBytesExpectedToSend))
}
super.urlSession(session, task: task, didSendBodyData: bytesSent, totalBytesSent: totalBytesSent, totalBytesExpectedToSend: totalBytesExpectedToSend)
}
// MARK: URLSessionDataDelegate
override func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
logger.logDataTask(dataTask, didReceive: data)
super.urlSession(session, dataTask: dataTask, didReceive: data)
}
// MARK: URLSessionDownloadDelegate
override func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
logger.logTask(downloadTask, didUpdateProgress: (completed: totalBytesWritten, total: totalBytesExpectedToWrite))
super.urlSession(session, downloadTask: downloadTask, didWriteData: bytesWritten, totalBytesWritten: totalBytesWritten, totalBytesExpectedToWrite: totalBytesExpectedToWrite)
}
} I still use an class PulseEventMonitor: EventMonitor {
let logger: NetworkLogger
init(logger: NetworkLogger) {
self.logger = logger
}
func request<Value>(_ request: DataStreamRequest, didParseStream result: Result<Value, AFError>) {
guard let task = request.task else { return }
let error: Error?
switch result {
case .success:
error = nil
case let .failure(failure):
error = failure
}
logger.logTask(task, didFinishDecodingWithError: error)
}
func request(_ request: DataRequest, didParseResponse response: DataResponse<Data?, AFError>) {
self.request(request, didFinishParsingWithError: response.error)
}
func request(_ request: DownloadRequest, didParseResponse response: DownloadResponse<URL?, AFError>) {
self.request(request, didFinishParsingWithError: response.error)
}
func request<Value>(_ request: DataRequest, didParseResponse response: DataResponse<Value, AFError>) {
self.request(request, didFinishParsingWithError: response.error)
}
func request<Value>(_ request: DownloadRequest, didParseResponse response: DownloadResponse<Value, AFError>) {
self.request(request, didFinishParsingWithError: response.error)
}
func request(_ request: Request, didFinishParsingWithError error: Error?) {
guard let task = request.task else { return }
switch error {
case .none:
logger.logTask(task, didFinishDecodingWithError: nil)
case let .some(AFError.responseSerializationFailed(reason: .decodingFailed(error: error))):
logger.logTask(task, didFinishDecodingWithError: error)
case let .some(error):
logger.logTask(task, didFinishDecodingWithError: error)
}
}
} Have not been crashing since. 🙂 |
I'm fairly consistently getting a crash in
NetworkLogger
. It looks like Pulse may be accessingURLSessionTask.currentRequest
andURLRequest.allHTTPHeaderFields
in unsafe ways.This issue is very similar to one I had with Datadog earlier. It appears
URLSessionTask
andURLRequest.allHTTPHeaderFields
may not be thread-safe. See Datadog's solution for more info.Reviewing
NetworkLogger
, it looks like Pulse is accessingURLSessionTask.currentRequest
andURLRequest.allHTTPHeaderFields
on a backgroundNSManagedObjectContext
queue.Should a solution similar to Datadog's be used? Where the data needed is copied (see
ImmutableRequest
) before sending to the background queue?The text was updated successfully, but these errors were encountered: