Aws-sdk-ios: Crash in AWSMobileClient.getTokens()

Created on 11 Mar 2019  路  12Comments  路  Source: aws-amplify/aws-sdk-ios

I'm getting crash reports signaling a crash in AWSMobileClient.getTokens(). This is possibly occuring when releaseSignInWait() is called without an active request waiting for sign in? Here's the stacktrace:

Crashed: NSOperationQueue 0x283dc0b20 (QOS: UNSPECIFIED)
0  libdispatch.dylib              0x235bc25e8 dispatch_group_leave + 124
1  AWSMobileClient                0x1054e0c60 closure #1 in closure #1 in AWSMobileClient.getTokens(_:) (AWSMobileClientExtensions.swift:719)
2  AWSMobileClient                0x1054db260 thunk for @escaping @callee_guaranteed (@guaranteed AWSTask<AWSCredentials>) -> (@out Any?) (<compiler-generated>)
3  AWSCore                        0x10569322c __56-[AWSTask continueWithExecutor:block:cancellationToken:]_block_invoke (AWSTask.m:331)
4  AWSCore                        0x105660670 __30+[AWSExecutor defaultExecutor]_block_invoke_2 (AWSExecutor.m:66)
5  AWSCore                        0x105660bdc -[AWSExecutor execute:] (AWSExecutor.m:131)
6  AWSCore                        0x105692e24 -[AWSTask runContinuations] (AWSTask.m:308)
7  AWSCore                        0x105692ab0 -[AWSTask trySetError:] (AWSTask.m:266)
8  AWSCore                        0x105694048 -[AWSTaskCompletionSource setError:] (AWSTaskCompletionSource.m:52)
9  AWSCore                        0x10569343c __56-[AWSTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 (AWSTask.m:340)
10 AWSCore                        0x1056932e4 __56-[AWSTask continueWithExecutor:block:cancellationToken:]_block_invoke (AWSTask.m:348)
11 AWSCore                        0x105660670 __30+[AWSExecutor defaultExecutor]_block_invoke_2 (AWSExecutor.m:66)
12 AWSCore                        0x105660bdc -[AWSExecutor execute:] (AWSExecutor.m:131)
13 AWSCore                        0x105692e24 -[AWSTask runContinuations] (AWSTask.m:308)
14 AWSCore                        0x105692ab0 -[AWSTask trySetError:] (AWSTask.m:266)
15 AWSCore                        0x105694048 -[AWSTaskCompletionSource setError:] (AWSTaskCompletionSource.m:52)
16 AWSCore                        0x1056afbec __61-[AWSURLSessionManager URLSession:task:didCompleteWithError:]_block_invoke (AWSURLSessionManager.m:351)
17 AWSCore                        0x1056938bc __63-[AWSTask continueWithExecutor:successBlock:cancellationToken:]_block_invoke (AWSTask.m:398)
18 AWSCore                        0x10569322c __56-[AWSTask continueWithExecutor:block:cancellationToken:]_block_invoke (AWSTask.m:331)
19 AWSCore                        0x105660670 __30+[AWSExecutor defaultExecutor]_block_invoke_2 (AWSExecutor.m:66)
20 AWSCore                        0x105660bdc -[AWSExecutor execute:] (AWSExecutor.m:131)
21 AWSCore                        0x105693090 -[AWSTask continueWithExecutor:block:cancellationToken:] (AWSTask.m:368)
22 AWSCore                        0x10569381c -[AWSTask continueWithExecutor:successBlock:cancellationToken:] (AWSTask.m:394)
23 AWSCore                        0x10569395c -[AWSTask continueWithSuccessBlock:] (AWSTask.m:404)
24 AWSCore                        0x1056aeb30 -[AWSURLSessionManager URLSession:task:didCompleteWithError:] (AWSURLSessionManager.m:216)
25 CFNetwork                      0x2369652f8 __51-[NSURLSession delegate_task:didCompleteWithError:]_block_invoke.241 + 280
26 ???                            0x28ef8236c60da4 (Missing)
27 ...

Crashlytics is also showing this detail:

crash_info_entry_0
BUG IN CLIENT OF LIBDISPATCH: Unbalanced call to dispatch_group_leave()

Calling AWSMobileClient.sharedInstance().releaseSignInWait() manually results in a crash occurring at line 680 of AWSMobileClientExtensions.swift

image

image

Which is why I wonder if the crashes are related.

It would also help greatly if the documentation around the need for releaseSignInWait() was more thorough. This is hopefully being addressed in https://github.com/aws-amplify/docs/issues/414.

Environment(please complete the following information):

  • AWS iOS SDK Version: 2.9.2
  • Dependency Manager: Cocoapods
  • Swift Version : 4.2
  • Device: Any
  • iOS Version: iOS 12.1.4
  • Specific to simulators: No
bug mobile client

All 12 comments

Hello @zigfreid5

You are correct. The code currently does not additionally validate if the releaseSignInWait() has an active request.

Couple of thoughts to determine what should be our behavior in such cases -

  1. Do we have a no-op and just return?
  2. We dispatch a notification that it was a no-op
  3. We let the behavior be as-is to make sure developers program correctly against the expected behavior.

What are your thoughts/ expectations of this call?

Thanks,
Rohan

The description says it will release "any" pending requests, and I don't think crashing should ever be an appropriate side-effect, so at a minimum, number 1 should be a given.

That being said, the behavior is a bit disjointed and unexpected. The handler for an unauthorized request happens entirely separate from the request itself. As mentioned, the current behavior is already causing confusion and further documentation has been requested. The problem is, developers are expected to implement the user state listener and include the call to releaseSignInWait() followed by signOut() for the user pool and federated token invalid states. Though the documentation says it's optional and only suggests to use it if the app has multiple users, if they don't implement it in the noted way, requests will hang indefinitely on token expiration... which is what brings us here.

One thing that's not clear is when the user state listener is triggered with these invalid token states. If it's only on a request, then implement your number 1 suggestion and close this issue. If there are other scenarios, then perhaps the request triggers should be handled separately in a way that releaseSignInWait() and signOut() can be called by the SDK on a failed re-authentication attempt, or the invalid token issue ignored and errors can be passed back to the request if needed? Similar to an onSuccess() onFailure() pair of closures?

Thanks for the detailed response @zigfreid5

I agree that crash is not a preferred option and at the very least we should make sure the SDK makes releaseSignInWait a no-op if there are no pending tasks.

Tagging @undefobj @nikhil-dabhade and @minbi to get their thoughts on this issue.

I had a discussion on another thread where the customer pointed out that we could remove the blocking behavior when the developer has not set the user state listener. This would eliminate the times that releaseSignInWait is called when there are no pending tasks.

For number 1, it probably makes sense to prevent the crash.

@zigfreid5 , are you calling releaseSignInWait in response to a *_INVALID_TOKENS signal? If so, we should investigate that for a possible miss fire.

@minbi I am not manually listening and responding to any AWS signals. I have only registered a user state listener via the .addUserStateListener(self) call.

I like the idea of not blocking requests when there is no user state listener registered in addition to implementing the number 1 suggestion. However, I think these token expiration situations may be better off with their own listener/handler as they are currently the only user states that expand on the "signed out" state and seem to have different requirements as far as the required use of releaseSignInWait, attempting to automatically re-sign in with saved credentials, etc.

If they had their own state listener/handler, the SDK could abstract away the necessary calls to releaseSignInWait + signOut and pass back specific authorization errors to the request if needed.

I have encountered this exact same problem while dealing with expired tokens. In my application I also use addUserStateListener to get notified about signedOutUserPoolsTokenInvalid.

The code currently does not additionally validate if the releaseSignInWait() has an active request.

What I am observing is that, after receiving signedOutUserPoolsTokenInvalid in the listener, if I do:

myAWSClient.releaseSignInWait()
myAWSClient.signOut()

Then the application crashes in the lines highlighted by @zigfreid5 .
However, if I instead call signIn with the credentials that I have stored in my app, then the login succeeds and the initial call that triggered the 400 error does receive the new token correctly. This suggests to me that there was, indeed, an active request.

Using:

  • AWS iOS SDK Version: 2.12.0
  • Dependency Manager: Cocoapods
  • Swift Version : 5

Hi, is there any update/fix on that issue? I am having the same issue at the moment.

Any updates ? Looks like we still have the issue. Calling releaseSignInWait crashes the app.

@undefobj @nikhil-dabhade and @minbi, any updates ?
We get crash when the listener triggers or if we call this anywhere in the code

Any update on this?

@royjit I'm using hosted UI with SDK 2.13.6 and the problem still occurs. The fix looks like it only covers the custom auth case. Can you also fix it for the hosted UI case? Thanks.

Screen Shot 2020-07-27 at 4 44 22 PM
Screen Shot 2020-07-27 at 4 44 46 PM

Still getting this on SDK 2.18.0 with hosted UI.

Crashed: com.apple.main-thread
0  libdispatch.dylib              0x1baff74c4 dispatch_group_leave.cold.1 + 36
1  libdispatch.dylib              0x1bafc8390 _dispatch_group_wake + 126
2  AWSMobileClient                0x1053af9f8 AWSMobileClient.releaseSignInWait() + 739 (AWSMobileClientExtensions.swift:739)
3  AmplifyPlugins                 0x1056b1d74 closure #1 in AuthorizationProviderAdapter.setupListener() + 4388281716 (AuthorizationProviderAdapter.swift:4388281716)
4  AWSMobileClient                0x1053a3538 partial apply for thunk for @escaping @callee_guaranteed (@unowned UserState, @guaranteed [String : String]) -> () + 4379817272 (<compiler-generated>:4379817272)
5  AWSMobileClient                0x1053afe24 closure #1 in closure #1 in AWSMobileClient.getTokens(_:) + 4379868708 (<compiler-generated>:4379868708)
6  AWSMobileClient                0x10539f664 thunk for @escaping @callee_guaranteed (@guaranteed AWSCognitoAuthUserSession?, @guaranteed Error?) -> () + 4379801188 (<compiler-generated>:4379801188)
7  AWSMobileClient                0x10538dd00 -[AWSCognitoAuth cleanUpAndCallGetSessionBlock:error:] + 402 (AWSCognitoAuth.m:402)
8  libdispatch.dylib              0x1bafc6134 _dispatch_call_block_and_release + 32
9  libdispatch.dylib              0x1bafc75ac _dispatch_client_callout + 20
10 libdispatch.dylib              0x1bafd37d4 _dispatch_main_queue_callback_4CF + 832
11 CoreFoundation                 0x1bb2a08d4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
12 CoreFoundation                 0x1bb29b58c __CFRunLoopRun + 1692
13 CoreFoundation                 0x1bb29abc8 CFRunLoopRunSpecific + 480
14 GraphicsServices               0x1c56835cc GSEventRunModal + 164
15 UIKitCore                      0x1bf44d744 UIApplicationMain + 1936
Was this page helpful?
0 / 5 - 0 ratings

Related issues

thomers picture thomers  路  3Comments

mackoj picture mackoj  路  5Comments

pawlowskialex picture pawlowskialex  路  4Comments

dougboberg picture dougboberg  路  5Comments

victorleungtw picture victorleungtw  路  4Comments