2

Recently I have started getting crash when trying to resolve an object. Following is the crash logs. I can see that in Container.swift at line 299 guard let currentObjectGraph = currentObjectGraph else { fatalError() } the application is not getting currentObjectGraph and it fails. What can be the probable cause? In my project, I have a global level assembler which adds all the Assembly from different frameworks. But when I am trying to resolve an object it's giving the crash. This is an intermediate issue:-

#15. Crashed: com.apple.NSURLSession-work
0  libswiftCore.dylib             0x109a1b95c specialized _assertionFailure(_:_:file:line:flags:) + 97848
1  Swinject                       0x1096d4994 Container.resolve<A, B> (entry : ServiceEntryProtocol, invoker : (B) -> Any) -> A? (Container.swift:299)
2  Swinject                       0x1096d2e54 Container._resolve<A, B> (name : String?, option : ServiceKeyOption?, invoker : ((B) -> Any) -> Any) -> A? (Container.swift:192)
3  Swinject                       0x1096d582c Container.resolve<A> (A.Type, name : String?) -> A? (Container.swift:281)
4  Swinject                       0x1096d5918 ContainerSwinjectResolver (Container.swift)
5  Commons                      0x10661e268 specialized static NetworkInterceptor.canInit(with : URLRequest) -> Bool (NetworkInterceptor.swift:67)
6  Commons                      0x10661c084 @objc static NetworkInterceptor.canInit(with : URLRequest) -> Bool (NetworkInterceptor.swift)
7  CFNetwork                      0x1822ec64c -[__NSURLSessionLocal _protocolClassForRequest:] + 188
8  CFNetwork                      0x1822ec7f4 -[__NSURLSessionLocal _request:isCacheEquivalentTo:] + 64
9  CFNetwork                      0x1822ec9c8 -[__NSURLSessionLocal _cfurlRequest:isCacheEquivalentTo:] + 172
10 CFNetwork                      0x18234fcc8 __CFURLCache::checkMemoryCache(__CFString const*, _CFURLRequest const*, NSURLSession const*) + 188
11 CFNetwork                      0x18234bfd0 __CFURLCache::CopyResponseForRequestWithCompletionHandler(_CFURLRequest const*, bool, NSURLSession const*, void (_CFCachedURLResponse const*) block_pointer) + 316
12 CFNetwork                      0x1824e4020 CFXURLCache::getResponseForTask(NSURLSessionTask const*, unsigned char, void (_CFCachedURLResponse const*) block_pointer) const + 84
13 CFNetwork                      0x18244a578 URLConnectionLoader::_loaderEvent_StartLoad(NSURLSessionTask const*) + 1116
14 CFNetwork                      0x18238007c -[__NSCFURLLocalSessionConnection withLoaderOnQueue:] + 72
15 CFNetwork                      0x1823806a4 -[__NSCFURLLocalSessionConnection _tick_initialize] + 92
16 CFNetwork                      0x18237fc24 __71-[__NSCFURLLocalSessionConnection initWithTask:delegate:delegateQueue:]_block_invoke + 40
17 libdispatch.dylib              0x1816dea54 _dispatch_call_block_and_release + 24
18 libdispatch.dylib              0x1816dea14 _dispatch_client_callout + 16
19 libdispatch.dylib              0x1816e896c _dispatch_queue_serial_drain$VARIANT$mp + 528
20 libdispatch.dylib              0x1816e92fc _dispatch_queue_invoke$VARIANT$mp + 340
21 libdispatch.dylib              0x1816e9d20 _dispatch_root_queue_drain_deferred_wlh$VARIANT$mp + 404
22 libdispatch.dylib              0x1816f203c _dispatch_workloop_worker_thread$VARIANT$mp + 644
23 libsystem_pthread.dylib        0x181986f1c _pthread_wqthread + 932
24 libsystem_pthread.dylib        0x181986b6c start_wqthread + 4
Balraj Singh
  • 3,381
  • 6
  • 47
  • 82
  • I see that you are resolving instances from different than main thread, which may be the source of the problem as `Container` is generally not thread safe. Are you using `Container.synchronize()`? – Jakub Vano Apr 06 '18 at 07:29
  • @JakubVano I am not using Container.synchronize(). – Balraj Singh Apr 06 '18 at 07:36

3 Answers3

4

To summarise the solution we converged to in the github issue:

When resolving services on multiple threads, you need to use the synchronised resolver, which provides the thread safety. Assembler doesn't quite support this yet (Swijnject#221) but you can work around this by

let synchronizedResolver = (assembler.resolver as! Container).synchronized()

and use this instance of Resolver every time you resolve() a service on all the threads.

Jakub Vano
  • 3,833
  • 15
  • 29
0

In my case, Its because .resolve(service) code called on other thread other than main thread. Moving that to main thread solved the crash.

Swinject fatalError() crash on resolve

Sanoj Kashyap
  • 5,020
  • 4
  • 49
  • 75
0

Our team had the same issue that occasionally caused crashes. Here is what I did to solve the problem:

  1. Do not register your instances inside the extension of the Container like the author of this article recommends.
  2. Instead, create a class with the instance of Container inside, so that in case if you need to pass resolver inside the register method, you would use synchronized resolver.

For a detailed explanation visit this article.

This approach solved the fatal error problem. It never occurred in the project again.

DoS
  • 11
  • 4
  • I rolled back the edit, because whilst this may theoretically answer the question, [it would be preferable](//meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. Please [edit] the answer with all relevant information. Make sure to use your own words, [answers comprised entirely of a quote (sourced or not) will often be deleted since they do not contain any original content](/help/referencing). In addition, you linked to what appears to be your own article. For that, read [how not to be a spammer](/help/promotion). – Adriaan Mar 28 '23 at 09:01