Skip to content
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: Container.swift line 299 Container.resolve<A, B> (entry : ServiceEntryProtocol, invoker : (B) -> Any) -> A? #344

Open
balrajOla opened this issue Apr 6, 2018 · 52 comments
Labels

Comments

@balrajOla
Copy link

@balrajOla balrajOla commented Apr 6, 2018

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
@jakubvano
Copy link
Member

@jakubvano jakubvano commented Apr 6, 2018

Crash log suggests, that you are resolving instances from different than main thread which may be the source of the problem - Container is generally not thread safe. Are you using Container.synchronize()?

.. I see that you have also opened SO question. I'd prefer to discuss the issue here, as it is a bit easier.

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 6, 2018

@jakubvano I am not using Container.synchronize(). The way i am using assembler is i have multiple modules which i am combining at AppDelegate level with an Assembler. and that instance of assembler is passed back to each module. Through which i am resolving. In the above scenario I am trying to resolve on a diff thread than main-thread. Which is the cause of the issue. Is there a better way to use this?

code how I am resolving is CommonKit.assembler?.resolver.resolve(SomeClass.Type). How can i get a container from assembler?

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Apr 6, 2018

I see, unfortunately, assembler by itself currently does not support thread safe access (#221). One way you could work around that would be

let synchronizedResolver = (assembler?.resolver as? Container)?.synchronize()

and use this synchronizedResolver instance every time you need to resolve a type.

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 6, 2018

@jakubvano Sure thanks. Will do that

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 6, 2018

@jakubvano Still getting the same issue. Sometimes. The issue is more prominent after swift4.1.

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 6, 2018

I am have implemented URLProtocol for intercepting network calls and log it. There are some dependencies which i am trying to resolve in public override class func canInit(with request: URLRequest) -> Bool function. Code below:-

public override class func canInit(with request: URLRequest) -> Bool {
       
       // need to resolve using synchronize because it will run on a diff thread
       if let synchronizedResolver = (CommonKit.assembler?.resolver as? Container)?.synchronize(),
           let config = synchronizedResolver.resolve(HTTPLoggerConfigurationType.self) {
           configuration = config
       }
       
      // Do something here
       return true
   }

It is always crashing here
guard let currentObjectGraph = currentObjectGraph else { fatalError() }

But this is only the piece of code which is not running on UI thread while resolving

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 7, 2018

@jakubvano I did some investigation on this. Even after using synchronize() func there is some threading issue. For which i started using Thread Sanitizer. Which reported that there is a Thread Race detected at:-

fileprivate func incrementResolutionDepth() {
        if resolutionDepth == 0 && currentObjectGraph == nil {
            currentObjectGraph = GraphIdentifier()
        }

I think due to which i am getting this issue.
Also if i put my resolve block of code into DispatchQueue.main.async. The Thread Sanitizer doesn't cry with the same issue. I think after using synchronize() method over container the entire operation is not thread safe. Can u please check and let me know.

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 9, 2018

@jakubvano any updated?

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Apr 9, 2018

Are you using .synchronized() resolver in the other calls (on the main thread) as well? Intended use is to create one instance of the synchronised resolver, and use it for all the resolve() calls.

Basically, synchronised resolver wraps resolve() calls in the lock based on the Container, which only works if all the resolve() calls are using the same lock.

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Apr 9, 2018

@jakubvano Thanks for this info. I got your point.

@balrajOla balrajOla closed this Apr 9, 2018
@jakubvano
Copy link
Member

@jakubvano jakubvano commented Apr 10, 2018

👍 I'm glad that you've managed to solve this issue.

@rkittinger
Copy link

@rkittinger rkittinger commented Jun 1, 2018

I am getting this error after updating to 2.4.0 and SwinjectStoryboard 2.0.1

@fans3210
Copy link

@fans3210 fans3210 commented Jun 27, 2018

@jakubvano, @balrajOla , I'm still a bit confused , about what you mentioned about using only one instance of the synchronised resolver, should I use that singleton resolver in the assemble method too? For instance: when I want to resolve something in the container.register method which is inside the assembly's assemble method. Like below:

I have a class called SomeClass which will be resolved in background thread like

let someInstance = globalThreadSafeResolver.resolve(SomeClass.self)!

, so for the register method, should I resolve using the thread safe resolver instead of the one provided by the register method like below?

container.register(SomeClass.self) { r in 
  //instead of using r, use the globalThreadSafeResolver
  SomeClass(config: globalThreadSafeResolver.resolve(Config.self)!)
}

Is it correct? Appreciated if you could give me some help!

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jun 27, 2018

@fans3210 It should not be necessary to use synchronised resolver for the nested resolutions, only for the one initiating the object graph. So in your case you should use

container.register(SomeClass.self) {  SomeClass(config: $0.resolve(Config.self)! }

@fans3210
Copy link

@fans3210 fans3210 commented Jun 27, 2018

@jakubvano , thanks, but that would be strange since I'm still facing issue of guard let currentObjectGraph = currentObjectGraph else { fatalError() } sometimes even though I'm using the synchronized resolver. Not often, but sometimes.
My app is a chat app and I'm using asyncdisplaykit which generate nodes in background thread to optimize the UI renderings.

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jun 27, 2018

@fans3210 If you are indeed using single globalThreadSafeResolver on all threads, this is probably some weird bug in Swinject implementation. Unfortunately, it will be quite difficult to pinpoint the problem without reproducible example...

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jun 27, 2018

Isn't it possible, that you are keeping an instance of Resolver obtained by constructor in factory closure? Something like

container.register(ServiceProvider.self) { ServiceProvider(resolver: $0) }

? That might explain the issue

@fans3210
Copy link

@fans3210 fans3210 commented Jun 28, 2018

@jakubvano . Nope. I used a lazy threadSafeResolver in my chatvc to resolve all the cell nodes. Currently I only use it to resolve. In the factory closure, I'm using the one provided by the assembly

@jakubvano jakubvano reopened this Jun 28, 2018
@jakubvano jakubvano added the bug label Jun 28, 2018
@Sali0m
Copy link

@Sali0m Sali0m commented Jul 3, 2018

Hello,
I'm experiencing the same issue on my project, and after reading the few first comments, I see that we never use synchronized()when resolving.

So just to be sure I understand correctly what I should do, here is an example.

public final class CoreConfigurator {
    public static let container: Container = Container()

     public static var someInstance: SomeClass {
        guard let branding = container.resolve(SomeClass.self) else { fatalError("SomeClass should be registered") }
        return someInstance
    }
}

Here is how we register it in the AppDelegate:
CoreConfigurator.container.register(SomeClass.self) { _ in SomeClass() }

If I'm not mistaken, what we actually should have is:

public final class CoreConfigurator {
    public static let container: Container = Container()
    private let resolver: Resolver = { return container.synchronize() }

     public static var someInstance: SomeClass {
        guard let branding = resolver.resolve(SomeClass.self) else { fatalError("SomeClass should be registered") }
        return someInstance
    }
}

Would this work correctly?
We have many registers, and due to GDPR, our registers could change following a user's action, since you said

Basically, synchronised resolver wraps resolve() calls in the lock based on the Container, which only works if all the resolve() calls are using the same lock.

I'm not sure it'd work correctly.

@fans3210
Copy link

@fans3210 fans3210 commented Jul 9, 2018

Today got some new findings that I received an error by using an assembly resolver in main thread:

screenshot 2018-07-09 11 30 32

screenshot 2018-07-09 11 29 23

Don't know whether is related. I did't use synchronised resolver for this case since it's resolving on main thread

@fans3210
Copy link

@fans3210 fans3210 commented Jul 9, 2018

For thread safe resolver, I also faced crash in this part:

screenshot 2018-07-09 11 39 09

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jul 10, 2018

@Sali0m from what I can tell, your modification should work correctly, provided you use .synchronized() resolver for all resolve calls (outside the register / initCompleted definitions).

@fans3210

Don't know whether is related. I did't use synchronised resolver for this case since it's resolving on main thread

If you are resolving instances on multiple threads, you need to use .synchronized() resolver on all of them. If you are not using it on the main thread, that might explain the behaviour you are experiencing.

@fans3210
Copy link

@fans3210 fans3210 commented Jul 10, 2018

@jakubvano , what I mentioned is a use case class which only works in main thread. So no need to use synchronised resolver. I faced that issue when enabled 'thread sanitizer' for xcode

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jul 10, 2018

what I mentioned is a use case class which only works in main thread. So no need to use synchronised resolver.

I am not sure I understand - is this class using a different Container than classes which work on the other threads?

@fans3210
Copy link

@fans3210 fans3210 commented Jul 11, 2018

@jakubvano for this image I showed:
https://user-images.githubusercontent.com/6023208/42429466-adb11f12-836b-11e8-90c0-636eb39d4894.png
No other thread is included. But thread sanitizer still gives me error.

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jul 11, 2018

@fans3210 data race is only possible if multiple threads are accessing the same memory location.

Looking more closely at your code, you are passing closure to the makeMarkReadUseCase, which is effectively the same as an example I mentioned in comment above - you are accessing the Resolver instance outside the .initCompleted method (it is just hidden a bit).

This is not a very good practice and can lead to issues (especially when multiple threads are in the play). If you have to do this though, you need to synchronize the resolver captured in the closure.
For more info see discussion in #266.

@fans3210
Copy link

@fans3210 fans3210 commented Jul 12, 2018

@jakubvano , sorry I'm not clear enough what you meant but the non-escaping closure shouldn't be the problem. May I show u some of the details of the code?

First, I have a use case class in my self-made framework target:

public class TestUseCase {
    
var param1
var param2
var coreDataStack: CoreDataStack

   public init(param1, param2, coreDataStack: CoreDataStack) {
     self.param1 = param1
     self.param2 = param2
    self.coreDataStack = coreDataStack
 }
    public func start() {
 
        //some async works internally but this function will return immediately in main thread
    }

    private func updateStates() {
      //code that update states, executed in main thread
    }
}

There are some internal functions which execute some async works but it won't affect the use case itself since all the functions in the use case class will return immediately.
I register this use case class in a UseCaseAssemblies class's assemble method:

public class UseCaseAssembly: Assembly {
    
    public init() {}
    
    public func assemble(container: Container) {
        container.register(TestUseCase.self) { r, param1, param2 in
            TestUseCase(param1:param1, param2, param2, coreDataStack: r.resolve(CoreDataStack.self)!)
        }
}

I only used the resolver to inject coredatastack in my use case. In my viewcontroller, I inject this usecase class and passing param1 with param2 using a non-escaping factory closure like this:

class TestVC: UIViewController {
    
    var makeTestUseCase: ((_ param1: String, _ param2: UserId) -> TestUseCase)!

}

U can see that param1 and param2 are passed by the vc, while coredatastack is from other assemblies

I register this vc in AppAssembly class

class AppAssembly: Assembly {
    
    func assemble(container: Container) {
        container.register(TestVC.self) { r in
            ChatMessagesVC(xxxxxx)
            }.initCompleted { r, vc in
               //inject the factory closure
                vc.makeTestUseCase = { param1, param2 in
                    r.resolve(TestUseCase.self, arguments: param1, param2)!
                }
            }
}

Could u kindly check this piece of code and tell me which part I'm using swinject in-properly? Since I'm not clear about what u mentioned about:
you are accessing the Resolver instance outside the .initCompleted method (it is just hidden a bit).

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jul 12, 2018

Issue is, that when you invoke your TestVC.makeTestUseCase closure during the view controller's life time, say

func doSomeAction() {
   let usecase = makeTestUsecase(param1, paramB)
   // ...
}

It is basically the same as calling

let usecase  = container.resolve(TestUseCase.self, arguments: param1, param2)!

And this is calling a non-synchronized Resolver outside the register / initCompleted blocks. It doesn't matter that this specific call is on the main thread - if you are accessing Container from multiple threads, all calls need to be made via .synchronized() resolver.

@fans3210
Copy link

@fans3210 fans3210 commented Jul 13, 2018

@jakubvano , thanks for the explanation. You mentioned:

if you are accessing Container from multiple threads, all calls need to be made via .synchronized() resolver.

But the thing is, I'm only accessing this non-escaping closure in main thread. There is no multi-thread case for this specific non-escaping closure. I'm a bit confused. Which part should I change?

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Jul 13, 2018

It doesn't matter that this specific call is on the main thread...

By this I meant that as long as there are any resolve calls on multiple threads, all resolve calls need to be made via .synchronize() resolver.

As I mentioned before this kind of Swinject usage is not really supported, but the simplest change to this closure you need to make would be:

vc.makeTestUseCase = { param1, param2 in
    (r as! Container).synchronize().resolve(TestUseCase.self, arguments: param1, param2)!
}

@fans3210
Copy link

@fans3210 fans3210 commented Jul 15, 2018

@jakubvano . Thanks a lot for your detailed explanation. I finally understood.

I think my issue was resolved, I handled the coded related to 'AsncDisplayKit' in main thread temporarily for now and I think the randomly crashed issue is resolved. Thanks again!

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Aug 31, 2018

Even I am facing the same issue after swift 4.1 update. did you solve this issue? Please let me know

`(lldb) bt

  • thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error
    frame #0: 0x00000001094ece60 libswiftCore.dylib_swift_runtime_on_report frame #1: 0x0000000109530910 libswiftCore.dylib_swift_stdlib_reportFatalErrorInFile + 128
    frame #2: 0x0000000109261b9c libswiftCore.dylibclosure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 284 frame #3: 0x00000001094d1a62 libswiftCore.dylibpartial apply forwarder for closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift.assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 34
    frame #4: 0x00000001094d2f19 libswiftCore.dylibclosure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Neverpartial apply forwarder with unmangled suffix ".823" + 9 frame #5: 0x0000000109261296 libswiftCore.dylibfunction signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <()> of Swift.StaticString.withUTF8Buffer((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A + 54
    frame #6: 0x00000001094d17eb libswiftCore.dylibpartial apply forwarder for closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 203 frame #7: 0x0000000109261296 libswiftCore.dylibfunction signature specialization <Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_guaranteed (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <()> of Swift.StaticString.withUTF8Buffer((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A + 54
    frame #8: 0x00000001093f29e0 libswiftCore.dylibfunction signature specialization <Arg[1] = Exploded> of Swift._assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 144 frame #9: 0x0000000109260cd0 libswiftCore.dylibSwift.assertionFailure(Swift.StaticString, Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 32
    frame #10: 0x00000001031d05d0 SwinjectContainer.resolve<A, B>(entry=(instance_type = 0x000060c0000da320 -> 0x00000001095a6738 libswiftCore.dylibInitialAllocationPool + 14008, protocol_witness_0 = 0x00000001031ee8a8 Swinjectprotocol witness table for Swinject.ServiceEntry<A> : Swinject.ServiceEntryProtocol in Swinject), invoker=0x00000001031d4b40 Swinjectpartial apply forwarder for reabstraction thunk helper <A, B> from @callee_guaranteed (@owned @callee_guaranteed (@in B) -> (@out Any)) -> (@out Any) to @callee_guaranteed (@in @callee_guaranteed (@in B) -> (@out Any)) -> (@out Any) at Container.swift, self=0x00006000000d9d00) at Container.swift:298 [opt]
    frame #11: 0x00000001031ce991 SwinjectContainer._resolve<A, B>(name=<unavailable>, option=nil, invoker=0x00000001031d4b70 Swinjectpartial apply forwarder for closure #1 ((Swinject.Resolver) -> Any) -> Any in Swinject.Container.resolve
    (A.Type, name: Swift.Optional<Swift.String>) -> Swift.Optional at Container.swift, self=) at Container.swift:192 [opt]
    frame #12: 0x00000001031cec36 SwinjectContainer.resolve<A>(name=nil, self=0x00006000000d9d00) at Container.swift:280 [opt] frame #13: 0x00000001031ceb62 SwinjectContainer.resolve(serviceType=, self=0x00006000000d9d00) at Container.swift:268 [opt]
    frame #14: 0x00000001031c6b73 Swinjectpartial apply for closure #1 in SynchronizedResolver.resolve<A>(_:) [inlined] closure #1 (self=<unavailable>, serviceType=<unavailable>) -> Swift.Optional<A> in Swinject.SynchronizedResolver.resolve<A>(A.Type) -> Swift.Optional<A> at SynchronizedResolver.swift:33 [opt] frame #15: 0x00000001031c6b63 Swinjectpartial apply for closure #1 in SynchronizedResolver.resolve(
    :) at SynchronizedResolver.swift:0 [opt]
    frame #16: 0x00000001031c1602 SwinjectSpinLock.sync<A>(action=0x00000001031c6b50 Swinjectpartial apply forwarder for closure #1 () -> Swift.Optional in Swinject.SynchronizedResolver.resolve(A.Type) -> Swift.Optional at SynchronizedResolver.swift, self=0x0000604000039be0) at SpinLock.swift:17 [opt]
    frame #17: 0x00000001031c6b1e SwinjectSynchronizedResolver.resolve<A>(serviceType=<unavailable>, self=<unavailable>) at SynchronizedResolver.swift:32 [opt] frame #18: 0x00000001031c6dd0 Swinjectprotocol witness for Resolver.resolve(
    :) in conformance SynchronizedResolver at SynchronizedResolver.swift:0 [opt]
    • frame #19: 0x000000010223570c MyAppServicesAssembly.reqresLogger.getter(self=0x0000600000077980) at ServicesAssembly.swift:494 frame #20: 0x00000001023c1563 MyAppLogRequest(request=Foundation.URLRequest @ 0x00007ffeedb55b40) at ReqresLogger.swift:19
      frame #21: 0x00000001023e5e24 MyAppBaseAPI.asObservable(request=Foundation.URLRequest @ 0x00007ffeedb55be0, sessionManager=0x00006080000db190, self=0x0000600000248fd0) at BaseAPI.swift:65 frame #22: 0x00000001023e5db9 MyAppBaseAPI.asObservable(request=Foundation.URLRequest @ 0x00007ffeedb55c30, self=0x0000600000248fd0) at BaseAPI.swift:61
      frame #23: 0x00000001023e65f2 MyAppBaseAPI.responseCollectionObservable<A>(queue=0x000000010ae2f680, request=Foundation.URLRequest @ 0x00007ffeedb55cd0, self=0x0000600000248fd0) at BaseAPI.swift:82 frame #24: 0x000000010235ab3b MyAppHomeAPI.getHomeFeatures(HomeId="39d83fbe", self=0x0000600000248fd0) at HomeAPI.swift:49
      frame #25: 0x0000000102439e59 MyAppFeatureManager.updateHomeFeatures(HomeId="39d83fbe-0608-43c6-a705-de0754acf4df", self=0x00006040002c4a60) at FeatureManager.swift:96 frame #26: 0x00000001021fcf64 MyAppSyncService.triggerHomeFeaturesSync(self=0x0000604000267940) at SyncService.swift:58
      frame #27: 0x00000001021fc006 MyAppSyncService.triggerSync(self=0x0000604000267940) at SyncService.swift:43 frame #28: 0x00000001021fc044 MyApp@objc SyncService.triggerSync() at SyncService.swift:0
      frame #29: 0x00000001024a5801 MyAppWeakTimer.invoke(self=0x000060000043df80) at WeakTimer.swift:28 frame #30: 0x00000001024a5894 MyApp@objc WeakTimer.invoke() at WeakTimer.swift:0
      frame #31: 0x0000000105fb591d CoreFoundation-[__NSCFTimer fire] + 141 frame #32: 0x00000001021fbc42 MyAppSyncService.activate(self=0x0000604000267940) at SyncService.swift:25
      frame #33: 0x000000010250035b MyAppHomePageService.activateServices(self=0x000060c0001b2280) at HomePageService.swift:43 frame #34: 0x0000000102506331 MyAppprotocol witness for HomePageService.activateServices() in conformance HomePageService at HomePageService.swift:0
      frame #35: 0x00000001021131f0 MyAppHomeScreenViewController.viewWillAppear(animated=false, self=0x00007f89c9805600) at HomeScreenViewController.swift:45 frame #36: 0x0000000102113253 MyApp@objc HomeScreenViewController.viewWillAppear(_:) at HomeScreenViewController.swift:0
      frame #37: 0x00000001071d7d60 UIKit-[UIViewController _setViewAppearState:isAnimating:] + 442 frame #38: 0x00000001071d85cf UIKit-[UIViewController __viewWillAppear:] + 131
      frame #39: 0x0000000107240266 UIKit-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 868 frame #40: 0x000000010723f463 UIKit-[UITabBarController transitionFromViewController:toViewController:] + 59
      frame #41: 0x000000010723b56d UIKit-[UITabBarController _setSelectedViewController:] + 410 frame #42: 0x000000010723b33c UIKit-[UITabBarController setSelectedViewController:] + 109
      frame #43: 0x000000010723f390 UIKit-[UITabBarController _tabBarItemClicked:] + 599 frame #44: 0x000000010702f3e8 UIKit-[UIApplication sendAction:to:from:forEvent:] + 83
      frame #45: 0x00000001074c9caf UIKit-[UITabBar _sendAction:withEvent:] + 597 frame #46: 0x000000010702f3e8 UIKit-[UIApplication sendAction:to:from:forEvent:] + 83
      frame #47: 0x00000001071aa7a4 UIKit-[UIControl sendAction:to:forEvent:] + 67 frame #48: 0x00000001071aaac1 UIKit-[UIControl _sendActionsForEvents:withEvent:] + 450
      frame #49: 0x00000001074cc6aa UIKit-[UITabBar _buttonUp:] + 113 frame #50: 0x000000010702f3e8 UIKit-[UIApplication sendAction:to:from:forEvent:] + 83
      frame #51: 0x00000001071aa7a4 UIKit-[UIControl sendAction:to:forEvent:] + 67 frame #52: 0x00000001071aaac1 UIKit-[UIControl _sendActionsForEvents:withEvent:] + 450
      frame #53: 0x00000001071a9a09 UIKit-[UIControl touchesEnded:withEvent:] + 580 frame #54: 0x00000001070a40bf UIKit-[UIWindow _sendTouchesForEvent:] + 2729
      frame #55: 0x00000001070a57c1 UIKit-[UIWindow sendEvent:] + 4086 frame #56: 0x0000000107049310 UIKit-[UIApplication sendEvent:] + 352
      frame #57: 0x000000010798a6af UIKit__dispatchPreprocessedEventFromEventQueue + 2796 frame #58: 0x000000010798d2c4 UIKit__handleEventQueueInternal + 5949
      frame #59: 0x0000000105f18bb1 CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 frame #60: 0x0000000105efd4af CoreFoundation__CFRunLoopDoSources0 + 271
      frame #61: 0x0000000105efca6f CoreFoundation__CFRunLoopRun + 1263 frame #62: 0x0000000105efc30b CoreFoundationCFRunLoopRunSpecific + 635
      frame #63: 0x000000010d2e7a73 GraphicsServicesGSEventRunModal + 62 frame #64: 0x000000010702e057 UIKitUIApplicationMain + 159
      frame #65: 0x00000001021fab67 MyAppmain at AppDelegate.swift:16 frame #66: 0x000000010ae54955 libdyld.dylibstart + 1
      frame #67: 0x000000010ae54955 libdyld.dylibstart + 1 (lldb)
      Partial Image:

screen shot 2018-08-31 at 3 56 17 pm

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Nov 26, 2018

@jakubvano Could you please update me regarding this issue?

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Dec 20, 2018

@jakubvano Could you please update me regarding this issue?
please update

@jakubvano
Copy link
Member

@jakubvano jakubvano commented Dec 20, 2018

@sanojbluejeans I would need some more specific information as to at what line of code / in what context are you experiencing this problem.

Original problem was related to the resolve calls from multiple threads to an unsynchronized resolver. Is your issue related to this?

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Dec 21, 2018

@jakubvano We are just calling a request based on some time interval to update some log info. I guess I tried by creating the synchronized resolver with which I was accessing the container but still I was facing the issue even crashes increased so reverted the same.

` let container = Container()

@objc static var shared = { () -> Assembly in
    let assembly = Assembly()
    assembly.registerServices()
    return assembly
}()`

func LogRequest(_ request: URLRequest) { Assembly.shared.reqresLogger.logRequest(request) // call call this request along with other in the app. }

var reqresLogger: ReqresLogger { return container.resolve(ReqresLogger.self)! }

logRequest is just for formatting it.

Is this above going to help you? Please let me know.

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Jan 15, 2019

@jakubvano This issue is turning out to be one of the most common occurring crash in our production app. Please help.

@Sali0m
Copy link

@Sali0m Sali0m commented Jan 15, 2019

@balrajOla, we had the same problem, but it turns out it was us that made this mess.

When you register something, you should synchronize the resolver to make sure it's up to date.

Or even easier, make a computed var of your resolver that synchronizes it

var resolver = { container.synchronize() }

I think that this should help you

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Feb 11, 2019

@balrajOla, we had the same problem, but it turns out it was us that made this mess.

When you register something, you should synchronize the resolver to make sure it's up to date.

Or even easier, make a computed var of your resolver that synchronizes it

var resolver = { container.synchronize() }

I think that this should help you

@balrajOla did you try mentioned a way to fix this issue? did it help?

@balrajOla
Copy link
Author

@balrajOla balrajOla commented Feb 11, 2019

@balrajOla This issue for me is fixed. Thanks

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Feb 12, 2019

@balrajOla What did you change? Could you please paste some code here related to fix?

@Sali0m
Copy link

@Sali0m Sali0m commented Feb 12, 2019

@balrajOla What did you change? Could you please paste some code here related to fix?

Did you try making a computed var of your resolver?

var resolver = { container.synchronize() }

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Feb 12, 2019

@balrajOla What did you change? Could you please paste some code here related to fix?

Did you try making a computed var of your resolver?

var resolver = { container.synchronize() }

I tried using the resolver but the issue was there. This change did not help much.

@Sali0m
Copy link

@Sali0m Sali0m commented Feb 12, 2019

Could you write an example of how you register in your container?
And how you resolve from it afterwards?

@sanoj00b
Copy link

@sanoj00b sanoj00b commented Feb 12, 2019

@jakubvano I got the crash again. I am partially printing :

In debug build: I am getting in Container.swift
0x10cef8492 <+2130>: leaq 0x14d97(%rip), %rax ; "**Infinite recursive call for circular dependency has been detected. To avoid the infinite call, 'initCompleted' handler should be used to inject circular dependency.**" 0x10cef8499 <+2137>: movabsq $-0x8000000000000000, %rcx ; imm = 0x8000000000000000 0x10cef84a3 <+2147>: orq %rax, %rcx 0x10cef84a6 <+2150>: leaq 0x14d72(%rip), %rdi ; "Fatal error" 0x10cef84ad <+2157>: leaq 0x14d0c(%rip), %r9 ; "/Users/Documents/Cry/Carthage/Checkouts/Swinject/Sources/Container.swift" 0x10cef84b4 <+2164>: movl $0xb, %esi 0x10cef84b9 <+2169>: movl $0x2, %edx 0x10cef84be <+2174>: movl $0xa4, %r8d 0x10cef84c4 <+2180>: pushq $0x0 0x10cef84c6 <+2182>: pushq $0xf2 0x10cef84cb <+2187>: jmp 0x10cef84fc ; <+2236> at Container.swift 0x10cef84cd <+2189>: leaq 0x14d4b(%rip), %rdi ; "Fatal error" 0x10cef84d4 <+2196>: leaq 0x14ce5(%rip), %r9 ; "/Users/Documents/Cry/Carthage/Checkouts/Swinject/Sources/Container.swift" 0x10cef84db <+2203>: movabsq $-0x2000000000000000, %rcx ; imm = 0xE000000000000000 0x10cef84e5 <+2213>: movl $0xb, %esi 0x10cef84ea <+2218>: movl $0x2, %edx 0x10cef84ef <+2223>: movl $0x0, %r8d 0x10cef84f5 <+2229>: pushq $0x0 0x10cef84f7 <+2231>: pushq $0x12a ; imm = 0x12A 0x10cef84fc <+2236>: pushq $0x2 0x10cef84fe <+2238>: pushq $0x5e 0x10cef8500 <+2240>: callq 0x10cf0af0a ; symbol stub for: Swift._assertionFailure(_: Swift.StaticString, _: Swift.String, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never 0x10cef8505 <+2245>: addq $0x20, %rsp 0x10cef8509 <+2249>: ud2
will it help?

@jcislinsky
Copy link

@jcislinsky jcislinsky commented Mar 31, 2019

Isn't it possible, that you are keeping an instance of Resolver obtained by constructor in factory closure? Something like

container.register(ServiceProvider.self) { ServiceProvider(resolver: $0) }

? That might explain the issue

@jakubvano So how can I inject resolver into dependencies? I use this pattern to increase variability of usage of container. Every dependency can resolver internally whatever it want.

@talron10
Copy link

@talron10 talron10 commented Nov 1, 2020

its 2020, but still crashing on this place (this time on line 302), and we are using only one single synchronized resolver everywhere in the app, if anyone shares this issue and have an insight it would be appreciated.

@abhilashRakuten
Copy link

@abhilashRakuten abhilashRakuten commented Dec 2, 2020

Still getting this crash: Fatal error: If accessing container from multiple threads, make sure to use a synchronized resolver.: file /Users/............/Carthage/Checkouts/Swinject/Sources/Container.swift, line 303 from crashlytics.

@Shockah
Copy link

@Shockah Shockah commented Sep 6, 2021

Also having the issue, despite using a SynchronizedResolver as suggested.

Crashed: <someProjectClass>.serialQueue
0  libswiftCore.dylib             0x18ade8398 _assertionFailure(_:_:file:line:flags:) + 1504
1  <projectName>                  0x102a88144 Container.resolve<A, B>(entry:invoker:) + 302 (Container.swift:302)
2  <projectName>                  0x102a8762c Container._resolve<A, B>(name:option:invoker:) + 190 (Container.swift:190)
3  <projectName>                  0x102a88dac Container.resolve<A>(_:name:) + 283 (Container.swift:283)
4  <projectName>                  0x102a9423c partial apply for closure #1 in SynchronizedResolver.resolve<A>(_:name:) + 4338795068 (<compiler-generated>:4338795068)
5  <projectName>                  0x102a92bdc SpinLock.sync<A>(action:) + 12 (SpinLock.swift:12)
6  <projectName>                  0x102a941c0 SynchronizedResolver.resolve<A>(_:name:) + 34 (SynchronizedResolver.swift:34)
7  <projectName>                  0x102a94210 protocol witness for Resolver.resolve<A>(_:name:) in conformance SynchronizedResolver + 4338795024 (<compiler-generated>:4338795024)
8  <projectName>                  0x102842544 Resolver.resolve<A>(_:) + 42 (SwinjectExtensions.swift:42)

@talron10
Copy link

@talron10 talron10 commented Sep 6, 2021

@Shockah
Copy link

@Shockah Shockah commented Sep 6, 2021

We actually solved it on our side by securing all of the instances of the resolver that were spreaded around. We kept a global reference of the SynchronizedResolver and just passed that around, as the resolver being passed in the app builder blocks were a non-sybchronized which caused the crashes

This is what we do already, and it doesn’t seem to help. At this point we’ll probably either move to a different library or just write our own solution for our internal use cases only.

@talron10
Copy link

@talron10 talron10 commented Sep 6, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
10 participants