Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLSessionDownloadTask stalls in background, slow to recover in foreground

I am creating a background session using this code...

    let configuration = URLSessionConfiguration.background(withIdentifier: UUID().uuidString)  
    configuration.sessionSendsLaunchEvents = true  
    configuration.isDiscretionary = false  
    self.session = Foundation.URLSession(configuration: configuration, delegate: self, delegateQueue: nil)  

...and download tasks using this code:

    let downloadTask = self.session.downloadTask(with: request as URLRequest)         
    downloadTask.resume()  

My request objects looks like this:

    let request = NSMutableURLRequest(url: someURL)  
    request.httpMethod = "POST"  
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")  
    do {  
        try request.httpBody = JSONSerialization.data(withJSONObject: someDictionary, options: JSONSerialization.WritingOptions())  
    } catch let error as NSError {  
        // logging calls  
    }  

The resources being download are ~20MB zip files.

I can run four concurrent downloads in the foreground with no issue. All expected delegate methods are called and the transfers complete at a normal speed.

The problem that I am seeing is that if I start the downloads in the foreground and then hit the home button the downloads will sometimes stall. I have tried keeping the device awake and the network spun up for an hour and the transfers still don't complete in the background. Additionally, when I bring the app back to the foreground the transfers do not immediately start again. If I let the app sit in the foreground for ~4 minutes, they will wake up and start working again. They resume at the percentage complete they were at when the app went into the background, and will transfer at normal speed until complete. At no time are there any errors, and the transfer is ultimately successful. It just "goes away" while in the background, and is very slow to resume when the app comes back to the foreground.

I am testing on an iPhone 6 running iOS 10. I am not connected to Xcode or external power and I am launching the app cold. I can reproduce the issue over both WiFi and cellular connections. I have deleted the app and reloaded it multiple times.

I am having trouble tracking this down because approximately 20% of the time it works fine. I have not found any particular set of variables that causes it to consistenly work or fail. It seems to happen more frequently when multiple downloads are occuring, and in that situation all of the downloads exhibit the behavior described above.

Any guidance would be greatly appreciated!

Matt

like image 406
Matthew Daugherty Avatar asked Oct 03 '16 17:10

Matthew Daugherty


1 Answers

The behavior you're describing sounds like a bug in iOS, but a few things I would try are:

  • Try setting discretionary to YES. This limits the rate of background relaunches.
  • Make sure you aren't accidentally creating a new background session with the same ID as an existing one (except when you've just been relaunched to handle events, and only after calling the completion handler) during a single launch.
  • Make sure you aren't creating subclasses of any of the classes involved—particularly NSURL or NSURLRequest.
  • Try setting shouldUseExtendedBackgroundIdleMode to YES.
  • Try adding enabling background fetch in UIBackgroundModes.

Neither of those last two should help, and if they do, file a bug.

Also, IIRC, your app can get punished if it gets relaunched too many times in the background, so if you're making a pile of short requests in a background task, you probably shouldn't. And if your app crashes when it gets relaunched in the background, that can also be very bad.

Finally, make sure that you're just going to the home screen. If you force-quit an app (double-tap, swipe), the background requests get terminated. And that is expected behavior.

If none of those tips help, please file a bug report at bugreporter.apple.com, because what you're describing is not the expected behavior.

like image 169
dgatwood Avatar answered Oct 21 '22 02:10

dgatwood