ibm-bluemix-mobile-services/bms-clientsdk-swift-push

Crashes in BMSPushClient.registerWithDeviceToken and BMSResponse.subscriptions

Closed this issue · 7 comments

Hi Team,

We are using BMSPush 2.0 and we have had a crash in BMSPushClient's registerWithDeviceToken at line 224 (Line 333 in latest Pod), due to a failed force cast to a String. We also see multiple crashes in subscriptions() function probably when the bluemix service returns an improper (null or non json) response to the pod and when it tries to retrieve subscriptions() from the improper response.

While doing a null check or a conditional cast would solve this issue, the better way is to not use force cast at all. Instead use 'nil coalescing' and handle the nil scenarios or have a default value for them. We see multiple places where force casts are used extensively even in the latest BMSPush pod.

Thank you,
Raj

HI @rajishere , Which version of SDK are you using ? Latest one 3.2.3. Are you using that ?

Hi @AnanthaKrish we are on 2.0. We are planning to upgrade to latest one in our coming app upgrades, but that will take sometime.

@rajishere we are no longer supporting the 2.0 version. please update to the 3.2.3

We would eventually, but I am afraid that won't resolve our issue completely. We should still get issues with the force casts used in the pod.

@rajishere after getting a 200 response status from the rest apis (registerWithDeviceToken and retrieveSubscriptionsWithCompletionHandler), your response file is empty ? or what data it have? Can you share me those info ? (please avoid the credentials and deviceIds) .

@AnanthaKrish Our code follows below algorithm in 2.0.

BMSPushClient.initializeWithAppGUID > registerWithDeviceToken > retrieveAvailableTagsWithCompletionHandler > subscribeToTags > retrieveSubscriptionsWithCompletionHandler. 

As indicated earlier, we have crashes that have happened when we call retrieveAvailableTagsWithCompletionHandler after registerWithDeviceToken in BMSResponse.swift. The logs indicate the text to be

"fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift, line 182".

Below is the sample call stack

Crashed: NSOperationQueue 0x170037880 :: NSOperation 0x17044a4d0 (QOS: DEFAULT)
0  libswiftCore.dylib             0x100887740 _TTSfq4n_s_n_n_n___TFs17_assertionFailureFTVs12StaticStringSS4fileS_4lineSu5flagsVs6UInt32_Os5Never + 164
1  libswiftCore.dylib             0x10078c3dc swift_errorInMain + 310
2  libswiftCore.dylib             0x10078c2a4 swift_unexpectedError + 26
3  BMSPush                        0x100682be4 type metadata accessor for JSONSerialization.ReadingOptions (BMSResponse.swift)
4  BMSPush                        0x100682300 Response.subscriptions() -> NSMutableArray + 132
5  BMSPush                        0x10067bd68 specialized BMSPushClient.(retrieveAvailableTagsWithCompletionHandler(completionHandler : (NSMutableArray?, Int?, String) -> ()) -> ()).(closure #1) (BMSPushClient.swift:479)
6  BMSPush                        0x10067c298 partial apply for BMSPushClient.(retrieveAvailableTagsWithCompletionHandler(completionHandler : (NSMutableArray?, Int?, String) -> ()) -> ()).(closure #1) + 17436
7  BMSCore                        0x100643a40 specialized Request.(send(requestBody : Data?, completionHandler : (Response?, Error?) -> ()?) -> ()).(closure #1) (Request.swift:79)
8  BMSCore                        0x10064368c partial apply for Request.(send(requestBody : Data?, completionHandler : (Response?, Error?) -> ()?) -> ()).(closure #1) (Request.swift)
9  BMSCore                        0x1006342a0 specialized BaseRequest.(buildAndSendRequest(url : URL, callback : (Response?, Error?) -> ()?) -> ()).(closure #1) (BaseRequest.swift:235)
10 BMSCore                        0x100634b50 partial apply for BaseRequest.(buildAndSendRequest(url : URL, callback : (Response?, Error?) -> ()?) -> ()).(closure #1) (BaseRequest.swift)
11 CFNetwork                      0x18d40834c __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 32
12 CFNetwork                      0x18d420048 __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 148
13 Foundation                     0x18d8cd814 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
14 Foundation                     0x18d812770 -[NSBlockOperation main] + 96
15 Foundation                     0x18d802b28 -[__NSOperationInternal _start:] + 612
16 Foundation                     0x18d8cfbb0 __NSOQSchedule_f + 228
17 libdispatch.dylib              0x18bcb69a0 _dispatch_client_callout + 16
18 libdispatch.dylib              0x18bcc4ad4 _dispatch_queue_serial_drain + 928
19 libdispatch.dylib              0x18bcba2cc _dispatch_queue_invoke + 884
20 libdispatch.dylib              0x18bcc6a50 _dispatch_root_queue_drain + 540
21 libdispatch.dylib              0x18bcc67d0 _dispatch_worker_thread3 + 124
22 libsystem_pthread.dylib        0x18bebf100 _pthread_wqthread + 1096
23 libsystem_pthread.dylib        0x18bebecac start_wqthread + 4

We have also seen crash in BMSPushClient.swift > registerWithDeviceToken.
Below is the error text

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.}: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift, line 182

And below is the call stack

Crashed: NSOperationQueue 0x170037620 :: NSOperation 0x170250c80 (QOS: DEFAULT)
0  libswiftCore.dylib             0x10089f740 _TTSfq4n_s_n_n_n___TFs17_assertionFailureFTVs12StaticStringSS4fileS_4lineSu5flagsVs6UInt32_Os5Never + 164
1  libswiftCore.dylib             0x1007a43dc swift_errorInMain + 310
2  libswiftCore.dylib             0x1007a42a4 swift_unexpectedError + 26
3  BMSPush                        0x100691a18 specialized specialized BMSPushClient.(registerWithDeviceToken(deviceToken : Data, WithUserId : String?, completionHandler : (String?, Int?, String) -> ()) -> ()).(closure #1) (BMSPushClient.swift:224)
4  BMSPush                        0x10068c69c specialized BMSPushClient.(registerWithDeviceToken(deviceToken : Data, WithUserId : String?, completionHandler : (String?, Int?, String) -> ()) -> ()).(closure #1) (BMSPushClient.swift)
5  BMSPush                        0x100690280 _TPA__TTSf2n_n_n_n_n_i_n_n___TFFC7BMSPush13BMSPushClient23registerWithDeviceTokenFT11deviceTokenV10Foundation4Data10WithUserIdGSqSS_17completionHandlerFTGSqSS_GSqSi_SS_T__T_U_FTGSqC7BMSCore8Response_GSqPs5Error___T_ (BMSPushClient.swift)
6  BMSCore                        0x10065ba40 specialized Request.(send(requestBody : Data?, completionHandler : (Response?, Error?) -> ()?) -> ()).(closure #1) (Request.swift:79)
7  BMSCore                        0x10065b68c partial apply for Request.(send(requestBody : Data?, completionHandler : (Response?, Error?) -> ()?) -> ()).(closure #1) (Request.swift)
8  BMSCore                        0x10064c2a0 specialized BaseRequest.(buildAndSendRequest(url : URL, callback : (Response?, Error?) -> ()?) -> ()).(closure #1) (BaseRequest.swift:235)
9  BMSCore                        0x10064cb50 partial apply for BaseRequest.(buildAndSendRequest(url : URL, callback : (Response?, Error?) -> ()?) -> ()).(closure #1) (BaseRequest.swift)
10 CFNetwork                      0x183dc434c __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke + 32
11 CFNetwork                      0x183ddc048 __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke + 148
12 Foundation                     0x184289814 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 16
13 Foundation                     0x1841ce770 -[NSBlockOperation main] + 96
14 Foundation                     0x1841beb28 -[__NSOperationInternal _start:] + 612
15 Foundation                     0x18428bbb0 __NSOQSchedule_f + 228
16 libdispatch.dylib              0x1826729a0 _dispatch_client_callout + 16
17 libdispatch.dylib              0x182680ad4 _dispatch_queue_serial_drain + 928
18 libdispatch.dylib              0x1826762cc _dispatch_queue_invoke + 884
19 libdispatch.dylib              0x182682a50 _dispatch_root_queue_drain + 540
20 libdispatch.dylib              0x1826827d0 _dispatch_worker_thread3 + 124
21 libsystem_pthread.dylib        0x18287b100 _pthread_wqthread + 1096
22 libsystem_pthread.dylib        0x18287acac start_wqthread + 4

Looking at the code I am suspecting, we are not handling bad responses (may be a force unwrapping of a null) or improper handling of JSON parsing is the issue.

We are also updating to 3.2.3 and are seeing few hiccups, but will take them in a seperate thread if needed.

@rajishere Hi, Yeah, it seems the success response is a bad JSON ... Have to handle them. Are you facing the same issue in 3.2.3? Meanwhile let me try out your scenario...