Support Topics Documentation Slack YouTube Blog

Using Backendless SDK while app is in the background


(Milen Marinov) #1

Hello,

For some time now I’ve been receiving crash reports from my iOS app that all point to this exception:
Fatal Exception: NSInternalInconsistencyException
this request has been neutered - you can’t call -sendResponse: twice nor after encoding it

I added some logs and saw the following happening:
3 | 1541676998293 | -[AppDelegate application:performFetchWithCompletionHandler:] line 185 $ Starting background fetch
4 | 1541677719526 | -[AppDelegate application:performFetchWithCompletionHandler:] line 185 $ Starting background fetch
5 | 1541677719680 | -[FINDataManager getSignalsForLocation:withCompletionHandler:]_block_invoke_2 line 207 $ Calling background fetch completion handler
6 | 1541677719680 | -[FINDataManager getSignalsForLocation:withCompletionHandler:]_block_invoke_2 line 207 $ Calling background fetch completion handler

(My app is open-source and you can find the code referenced above here)

In AppDelegate application:performFetchWithCompletionHandler: I make an async call through Backendless SDK. However, it looks like execution is paused and none of the completion blocks (neither “response”, nor “error”) is called until the second system call to AppDelegate application:performFetchWithCompletionHandler: is made. Then both Backendless requests receive their callbacks at the same time!

Do you have any explanation why this might be happening? I do remember Backendless SDK switching execution of async calls to different threads a while ago.
What is the suggested way for using the SDK for background fetching?


(Oleg Vyalyh) #2

Hi, Milen. I’ve created inner task to investigate the problem (BKNDLSS-17776).
The developer will answer you here when there is progress.


(Olga Danylova) #3

Hello Milen,
Please provide steps to reproduce the issue for your app.

Regards,
Olga


(Milen Marinov) #4

Hi Olga,

I managed to further narrow down the problem! It happens when a request made during background fetch fails (timeout in my case, not sure if applicable to other fail reasons).

The general steps for reproducing it are:

  1. On a real device setup Network Link Conditioner to 100% loss
  2. Start app in background fetch mode (“Launch app due to a background fetch event” option in the Xcode scheme)
  3. In application:performFetchWithCompletionHandler: make an async Backendless call (backendless.geoService getPoints in my case, again not sure if problem is specific to this method or all Backendless calls)
  4. Wait more than a minute in order for the request to time-out
  5. Send another background fetch event (Debug > Simulate Background Fetch from Xcode menu) (This is done just to resume app execution because the allowed time for background fetch is around 30 seconds)

Expected result:
The request fails with a time-out.

Actual result:
The error block is called twice with two different errors:
**FAULT = ‘-1001’ [NSURLErrorDomain]
**FAULT = ‘0’ [HttpEngine: INVALID statusCode 0] <HttpEngine: INVALID statusCode 0>

In my particular case this results in the background fetch completion block being called twice and hence the crash.

Here are the relevant logs:
2018-11-13 10:35:36.826475+0200 Help A Paw[14121:1946549] -[AppDelegate application:performFetchWithCompletionHandler:] line 185 $ [FIN] Starting background fetch with completion handler: <NSMallocBlock: 0x16332f390>

2018-11-13 10:36:37.611525+0200 Help A Paw[14121:1946549] -[FINDataManager getSignalsForLocation:withCompletionHandler:]_block_invoke line 200 $ [FIN] Getting signals failed with error: FAULT = ‘-1001’ [NSURLErrorDomain] <The request timed out.>

2018-11-13 10:36:37.617112+0200 Help A Paw[14121:1946549] -[FINDataManager getSignalsForLocation:withCompletionHandler:]_block_invoke line 200 $ [FIN] Getting signals failed with error: FAULT = ‘0’ [HttpEngine: INVALID statusCode 0] <HttpEngine: INVALID statusCode 0>

2018-11-13 10:36:37.620044+0200 Help A Paw[14121:1946549] -[FINDataManager getSignalsForLocation:withCompletionHandler:]_block_invoke_2 line 207 $ [FIN] Calling background fetch completion handler: <NSMallocBlock: 0x16332f390>

2018-11-13 10:36:37.622973+0200 Help A Paw[14121:1946549] -[FINDataManager getSignalsForLocation:withCompletionHandler:]_block_invoke_2 line 207 $ [FIN] Calling background fetch completion handler: <NSMallocBlock: 0x16332f390>

As you can see by the address of the NSMallocBlock the same block is called twice - so it’s not two seperate requests failing at the same time.

And here is the error block:
error:^(Fault *fault) {
CLS_LOG(@"[FIN] Getting signals failed with error: %@", fault.description);

    self.lastSignalCheckLocation = nil;
    
    if (completionHandler != nil)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            CLS_LOG(@"[FIN] Calling background fetch completion handler: %@", completionHandler);
            completionHandler(UIBackgroundFetchResultFailed);
        });
    }
}];

Let me know if I can further assist you in solving this issue!


(Olga Danylova) #5

Hello Milen,

iOS-SDK returns response in the thread which it has been invoked in and this behavior is correct.

Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘this request has been neutered - you can’t call -sendResponse: twice nor after encoding it’

seems to be similar to this problem. completionHandler() is called twice in your error block and causes that crash.

Maybe some of these topics could help you?
iOS 8 NSInternalInconsistencyException
NSInternalInconsistencyException when running background fetch with a loop
https://github.com/OneSignal/OneSignal-iOS-SDK/issues/148 with this fix https://github.com/OneSignal/OneSignal-iOS-SDK/commit/cc7ae438bfd9cb325b63b4f0ae9771751ed4c68f

I’ve checked your app with iOS-SDK v5.2.3.

Regards,
Olga


(Milen Marinov) #6

Hello Olga,

Indeed the problem is that completionHandler() is called twice but this happens because the error block is called twice for the same request!
When you make an async request to Backendless SDK it should call back either the response or the error block and do that just once, right?

P.S. I’m also using v5.2.3


(Olga Danylova) #8

I see. Sorry for misunderstanding, working on it.

Regards,
Olga


(Olga Danylova) #9

Hello Milen,

Please check with iOS-SDK v5.2.4.

Regards,
Olga


(Milen Marinov) #10

The problem is fixed! Thanks a lot, Olga!