DispatchSourceTimer Not Firing in Local Push Connectivity Extension When App Is in Foreground and Device Is Locked

Hi,

I’m using a Local Push Connectivity Extension and encountering an issue with DispatchSourceTimer.

In my extension, I create a DispatchSourceTimer that is supposed to fire every 1 second. It works as expected at first. However, when the app is in the foreground and the device is locked, the timer eventually stops firing after 1–3 hours.

The extension process is still alive, and no errors are thrown

Has anyone experienced this behavior? Is this a known limitation for timers inside NEAppPushProvider, or is the extension being deprioritized silently by the system?

Any insights or suggestions would be greatly appreciated. Thanks!

I’m using a Local Push Connectivity Extension and encountering an issue with DispatchSourceTimer. In my extension, I create a DispatchSourceTimer that is supposed to fire every 1 second.

First off, please don't do that. Cumulatively, that adds up to a lot of wasted work and there isn't anything an idle local push extension should need to be doing once ever second. Having said that, I'm not aware of any reason why this wouldn't work.

It works as expected at first. However, when the app is in the foreground and the device is locked, the timer eventually stops firing after 1–3 hours.

Does your app actually need to be in the foreground to trigger this? That's actually quite weird and, if it's actually required, makes me suspect that the issue here is actually something your app is doing that is interferring with you extension. There's no reason that would have mattered to the broader system.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

There’s a requirement for our app: the iOS client must send a keep-alive packet every second.

I'm sorry but, setting all other issues aside, that requirement is not reasonable. That level of network activity is going to prevent basically "all" device sleep, with a corresponding decrease in battery life. Proper keep-alive activity should generally be occurring in "minutes", not "seconds".

Moving to here, I have a few different comments:

based on our stress test logs, we’ve observed that DispatchSourceTimer gets suspended for 30 seconds to 1 minute during screen lock.

  • I'm not aware of any specific behavior/issue that would cause that behavior, particularly not within the network extension itself. To whatever extent the system is involved, I suspect this is being caused by the interaction of multiple components, not any single "choice".

  • If you want to investigate this in more depth, then the first thing I would do is validate your understanding of exactly what's going on with the most basic possible implementation. That will either rule out the systems direct involvement (because it dones't happen with a basic case) or simplify a systems level investigation (because you can now replicate it with a trivial sample).

  • Related to that point, make sure you also test the case where your app isn't running at ALL. There shouldn't be any direct entanglement between your primary app and your connectivity extension.

  • Is your extension able to receive data from your server during this time window? As I noted above, this kind of timeout frequency is far higher than it should be, but the other side of that is that your extension should be able to receiving incoming traffic at any time. Blocking input traffic would make this a much more serious issue.

  • On the code side, how is your timer configured, what queue is it targeting, and is there any other activity that might block that queue. The simplest explanation for this kind of delay is that the target queue was busy doing something else.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

DispatchSourceTimer Not Firing in Local Push Connectivity Extension When App Is in Foreground and Device Is Locked
 
 
Q