Hello everybody.
I have a Swift Task which calls 2(minimum) to 3 (maximum) REST calls sequentially upon specific cases. They are not long run processes like files.
I am wondering what is the alive duration of a Task if the device is locked. I noticed that sometimes it is executed in the background properly, some others is paused and resumed when the device is unlocked again and sometime we got timeout (in more than 10 minutes).
Is any official time limit documented where the iOS system suspends a Task?
Is any official time limit documented where the iOS system suspends a Task?
That question doesn’t make sense. Lemme explain a bit of background about what’s going on here, and then you can reply back if you have follow-up questions.
Swift concurrency runs entirely within a process. Execution of a progress is dependent on two things:
- The CPU must be running. If the CPU is asleep, all processing stops. This applies to all Apple platforms.
- On iOS and its child platforms, the system can suspend a process. When that happens the CPU may or may not be running, but the process itself doesn’t run.
If a process isn’t running then none of the threads in that process execute. The Swift concurrency runtime uses worker threads to execute Swift tasks, and if those threads don’t execute then no Swift tasks execute. Likewise for the Dispatch runtime.
iOS and its child platforms typically suspend the process shortly after the user moves it to the background. However, there are a variety of things that can prevent that suspension. I have a bunch of info, and links to more info, in iOS Background Execution Limits and UIApplication Background Task Notes.
Process suspension isn’t a problem if your task is just working on the CPU. However, if your task is interacting with other stuff, like using network, then process suspension can cause weird behaviour. Consider this sequence:
- You start a task.
- It uses a
URLSessiondata task to request a resource from a server. - While the request is in flight, the system suspends your process.
- If your process stays suspended for any significant amount of time, the server will give up on you and drop the connection.
- Eventually the system resume your process…
- At which point your
URLSessiondata task fails with an error.
IMPORTANT The above is a conceptual description of the problem. In reality, step 3 will result in your network connections being defuncted. That’ll promptly trigger an error on the server. TN2277 Networking and Multitasking talks about this in more detail, although note that it uses an old term, socket resource reclaim, rather than the newer term defuncting.
So, what should you do about this? In the case of networking there are four basic strategies:
- Prevent your process from suspending.
- Stop any in-flight networking when your process becomes eligible for suspension.
- Let things fail and then deal with the errors.
- In the case of
URLSessionspecifically, use a background session.
Which option is best very much depends on your circumstances. Here are some links that you’ll likely find useful:
- iOS Background Execution Limits (I also mentioned this earlier)
- UIApplication Background Task Notes (I also mentioned this earlier)
- Moving to Fewer, Larger Transfers
- Testing Background Session Code
Finally, a couple of general points:
- While I’ve mostly addressed this from a networking perspective, you’ll encounter similar problems any time you interact with the ‘outside’ world. Even something as simple as scheduling a timer can be confusing, because the exact behaviour you see depends on whether it’s your process that gets suspended, or the CPU, or both.
- If you’re on iOS or one of its child platforms and the system suspends your process, then you have to deal with the fact that the system might never resume it. The system might terminate a suspended process without ever resuming it again. The most common reason for this is memory pressure — the system wants to reclaim the memory used by your process — but there are many others. For example, if your app is suspended in the background and the user updates it to a new version, the system will terminate the app before running the upgrade.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"