I got a single entry point for any requests in my project (something like "RequestManager") that does the following:
fileprivate func _executeRequest(withPath path: String,
params: [String: Any]? = nil,
method: HTTPMethod,
tokenNeeded: Bool = true,
encoding: ParameterEncoding = URLEncoding.default
) -> Observable<DataResponse<Any>> {
return Observable.create { [weak self] observer -> Disposable in
guard let `self` = self else { return Disposables.create() }
let request = self.sessionManager.requestWithoutCache(
self.defaultPath + path,
method: method,
parameters: params,
encoding: encoding,
headers: self.headers(with: tokenNeeded))
.validate()
.responseJSON { response in
switch response.result {
case .success:
observer.onNext(response)
observer.onCompleted()
case .failure(let error):
let fagError = FiveAndGoError.Network.from(error: error, metadata: response.data)
observer.onError(fagError)
}
}
return Disposables.create {
request.cancel()
}
}
}
Regular requests being sent.
Some of the requests crashing.
I cannot reproduce this in my debug/staging environment through Xcode
But I got a lot of users' crashes sent to Fabric. The following contains stack trace of the crash:
Crashed: com.apple.main-thread
0 CFNetwork 0x187e8d628 HTTPParser::HTTPParser(__CFAllocator const*, HTTPParserClient*, HTTPParser*) + 48
1 CFNetwork 0x187d581d0 HTTPMessage::commonInitialization(unsigned char, HTTPMessage const*) + 248
2 CFNetwork 0x187d581d0 HTTPMessage::commonInitialization(unsigned char, HTTPMessage const*) + 248
3 CFNetwork 0x187d58360 HTTPMessage::HTTPMessage(HTTPMessage const*) + 112
4 CFNetwork 0x187e8e670 HTTPRequestMessage::HTTPRequestMessage(HTTPRequestMessage const*) + 36
5 CFNetwork 0x187d38ed8 HTTPRequest::HTTPRequest(HTTPRequest const*) + 24
6 CFNetwork 0x187d3b5e4 URLRequest::initialize(URLRequest const*, unsigned char) + 640
7 CFNetwork 0x187cf2f40 _createRequestCopy(__CFAllocator const*, _CFURLRequest const*, unsigned char) + 152
8 CFNetwork 0x187c77f48 -[NSURLRequest mutableCopyWithZone:] + 44
9 libswiftFoundation.dylib 0x10f7560cc specialized URLRequest.init(_bridged:) + 36
10 libswiftFoundation.dylib 0x10f73afd0 static URLRequest._unconditionallyBridgeFromObjectiveC(_:) + 36
11 Alamofire 0x107901c58 DataRequest.request.getter (Request.swift:108)
12 Alamofire 0x1079377fc DataRequest.validate() (Validation.swift:84)
13 Core 0x10d71e494 closure #1 in RequestManager._executeRequest(withPath:parameters:method:tokenNeeded:deviceIdNeeded:encoding:) (RequestManager.swift:245)
14 Core 0x10d71f80c partial apply for closure #1 in RequestManager._executeRequest(withPath:parameters:method:tokenNeeded:deviceIdNeeded:encoding:) (<compiler-generated>)
15 RxSwift 0x10c6be454 AnonymousObservable.run<A>(_:cancel:) (<compiler-generated>)
16 RxSwift 0x10c6e6a94 Producer.subscribe<A>(_:) (Producer.swift:18)
17 RxSwift 0x10c6a4dc4 CatchSink.run() (Catch.swift:123)
18 RxSwift 0x10c6a5354 Catch.run<A>(_:cancel:) (Catch.swift:165)
19 RxSwift 0x10c6e6a94 Producer.subscribe<A>(_:) (Producer.swift:18)
20 RxSwift 0x10c705944 SwitchSink.run(_:) (Switch.swift:67)
21 RxSwift 0x10c706b7c FlatMapLatest.run<A>(_:cancel:) (Switch.swift:231)
22 RxSwift 0x10c6e6a94 Producer.subscribe<A>(_:) (Producer.swift:18)
23 RxSwift 0x10c6d9320 MergeSink.run(_:) (Merge.swift:508)
24 RxSwift 0x10c6d9b70 FlatMap.run<A>(_:cancel:) + 312
25 RxSwift 0x10c6e6a94 Producer.subscribe<A>(_:) (Producer.swift:18)
26 RxSwift 0x10c6a4dc4 CatchSink.run() (Catch.swift:123)
27 RxSwift 0x10c6a5354 Catch.run<A>(_:cancel:) (Catch.swift:165)
28 RxSwift 0x10c6e6a94 Producer.subscribe<A>(_:) (Producer.swift:18)
29 RxSwift 0x10c6de500 ObservableType.subscribe(onNext:onError:onCompleted:onDisposed:) (<compiler-generated>)
30 MyProject 0x102d7bf9c SomeModel.handleConfirmedStatus() (<compiler-generated>)
31 MyProject 0x102d7a640 SomeModel.handleExistingDataFlow(someDataModel:) (SomeModel+CreateFlowBindings.swift:141)
32 MyProject 0x102d7999c closure #1 in SomeModel.fetchCurrentData() (<compiler-generated>)
33 MyProject 0x102d7e814 partial apply for thunk for @escaping @callee_guaranteed (@guaranteed SomeDataModel?) -> () (<compiler-generated>)
34 RxSwift 0x10c6de820 closure #1 in ObservableType.subscribe(onNext:onError:onCompleted:onDisposed:) (<compiler-generated>)
35 RxSwift 0x10c6dea20 partial apply for closure #1 in ObservableType.subscribe(onNext:onError:onCompleted:onDisposed:) (<compiler-generated>)
36 RxSwift 0x10c697aa0 AnonymousObserver.onCore(_:) (<compiler-generated>)
37 RxSwift 0x10c6e1078 ObserverBase.on(_:) (ObserverBase.swift:21)
38 RxSwift 0x10c6e11a4 protocol witness for ObserverType.on(_:) in conformance ObserverBase<A> (<compiler-generated>)
39 RxSwift 0x10c700404 Sink.forwardOn(_:) (Sink.swift:36)
40 RxSwift 0x10c6a4fb0 CatchSink.on(_:) (Catch.swift:131)
41 RxSwift 0x10c6a51f0 protocol witness for ObserverType.on(_:) in conformance CatchSink<A> (<compiler-generated>)
42 RxSwift 0x10c700404 Sink.forwardOn(_:) (Sink.swift:36)
43 RxSwift 0x10c7063c8 SwitchSinkIter._synchronized_on(_:) (Switch.swift:171)
44 RxSwift 0x10c707888 SynchronizedOnType.synchronizedOn(_:) (SynchronizedOnType.swift:15)
45 RxSwift 0x10c706204 SwitchSinkIter.on(_:) (Switch.swift:145)
46 RxSwift 0x10c7064d0 protocol witness for ObserverType.on(_:) in conformance SwitchSinkIter<A, B, C> (<compiler-generated>)
47 RxSwift 0x10c700404 Sink.forwardOn(_:) (Sink.swift:36)
48 RxSwift 0x10c6d49cc MapSink.on(_:) (Map.swift:45)
49 RxSwift 0x10c6d4b68 protocol witness for ObserverType.on(_:) in conformance MapSink<A, B> (<compiler-generated>)
50 RxSwift 0x10c6d3564 Just.subscribe<A>(_:) (Just.swift:83)
51 RxSwift 0x10c6d4ef8 Map.run<A>(_:cancel:) (Map.swift:100)
52 RxSwift 0x10c6e6f08 closure #1 in Producer.subscribe<A>(_:) (Producer.swift:26)
53 RxSwift 0x10c6be994 specialized CurrentThreadScheduler.schedule<A>(_:action:) (<compiler-generated>)
54 RxSwift 0x10c6e6bb0 Producer.subscribe<A>(_:) (<compiler-generated>)
55 RxSwift 0x10c705fac SwitchSink.on(_:) (Switch.swift:102)
56 RxSwift 0x10c706144 protocol witness for ObserverType.on(_:) in conformance SwitchSink<A, B, C> (<compiler-generated>)
57 RxSwift 0x10c700404 Sink.forwardOn(_:) (Sink.swift:36)
58 RxSwift 0x10c6a4fb0 CatchSink.on(_:) (Catch.swift:131)
59 RxSwift 0x10c6a51f0 protocol witness for ObserverType.on(_:) in conformance CatchSink<A> (<compiler-generated>)
60 RxSwift 0x10c700404 Sink.forwardOn(_:) (Sink.swift:36)
61 RxSwift 0x10c6be1a0 AnonymousObservableSink.on(_:) (Create.swift:50)
62 RxSwift 0x10c6be2fc protocol witness for ObserverType.on(_:) in conformance AnonymousObservableSink<A> (<compiler-generated>)
63 RxSwift 0x10c6e15c0 partial apply (<compiler-generated>)
64 RxSwift 0x10c697ba0 AnyObserver.on(_:) (<compiler-generated>)
65 RxSwift 0x10c6e1358 ObserverType.onNext(_:) (ObserverType.swift:27)
66 Core 0x10d71e89c closure #1 in closure #1 in RequestManager._executeRequest(withPath:parameters:method:tokenNeeded:deviceIdNeeded:encoding:) (RequestManager.swift:250)
67 Alamofire 0x107915f30 partial apply for specialized (<compiler-generated>)
68 Alamofire 0x1078f5910 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
69 libdispatch.dylib 0x1870fd6c8 _dispatch_call_block_and_release + 24
70 libdispatch.dylib 0x1870fe484 _dispatch_client_callout + 16
71 libdispatch.dylib 0x1870ddb34 _dispatch_main_queue_callback_4CF$VARIANT$armv81 + 1012
72 CoreFoundation 0x187655ce4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
73 CoreFoundation 0x187650bac __CFRunLoopRun + 1964
74 CoreFoundation 0x1876500e0 CFRunLoopRunSpecific + 436
75 GraphicsServices 0x1898c9584 GSEventRunModal + 100
76 UIKitCore 0x1b48a0c00 UIApplicationMain + 212
77 MyProject 0x102bfe184 main (AppDelegate.swift:22)
78 libdyld.dylib 0x18710ebb4 start + 4
Some of the crash reports have different trace before the 14th step (calling function from RequestManager), so it crashes from different places of the app.
The problem is always in calling request getter of the Request.swift (line 108) while validation. Did some investigation, and I think it caused during bridging between swift/obj-c. And maybe converting a computed property into stored one could help, but since I cannot reproduce it I can't be sure either.
Any suggestions on how to fix or at least investigate the issue are highly appreciated!
Alamofire version: 4.7.3, 4.8.1
Xcode version: 10.1
Swift version: 4.2
Platform(s) running Alamofire: iOS
macOS version running Xcode: 10.14.3
It looks like the problem lays in the debugging tool we're using. Sorry for bothering
Yes, the underlying C++ implementation of NSURLRequest has threading issues when touched from threads apart from the creating thread, leading to issues with tools that swizzle their way into the networking stack, as well as Alamofire itself sometimes. Alamofire 5 has a specific fix for crashes like this where it copies the request before taking it off the creating queue, which seems to help.
thank you for pointing it, will try
Is there a workaround until Alamofire 5 is released?
@wgrand It's not certain what's causing this particular crash. If it is a queueing issue, one option might be to ensure all of your URLRequest creation is happening on the same queue. In Alamofire 4, request creation is synchronous on the calling queue, so you may need to ensure that request is always called on the same queue. Additionally, if you're creating URLRequests manually, copying them before dispatching to another queue might fix the issue.
Most helpful comment
It looks like the problem lays in the debugging tool we're using. Sorry for bothering