Dispatch queue stop working when use ARKit on iOS 14.2 and above

We have an issue within our main app and it's quite frustrating as we now can't promote them as planned and first have to figure out a workaround for this issue or wait for a solution.

ARKit Bug:
ARKit causes the dispatch queue(default-qos) to stop working. I have a simple code to simulate this scene. In the official ARKit demo.

https://github.com/titman/arkit-14_2_bug/tree/master/arkit-by-example

When using [CMMotionManager startDeviceMotionUpdatesUsingReferenceFrame:toQueue:withHandler:] method to open sensor monitor, and deviceMotionUpdateInterval setting is 0.04.
print logs use callback block, about 1~15 mins later, CMMotionManager will stop working. This issue will be reproduced with high probability,you need to try multi times.

Once a block occurs, it can never be recovered.



Any suggestions? Thank you very much!

Replies

I'm seeing a similar bug reported by a customer. I work on Firebase and a customer reported an issue (https://github.com/firebase/quickstart-unity/issues/918) for which the only explanation is that the "dispatch function" specified to dispatch_async_f() is never called back. More concretely, calling dispatch_async_f() works for a while, then, at some indeterminate point in the future, it fails to call back the given function without any explanation. The customer reports that they are using "ARFoundation" (which almost certainly uses ARKit under the hood) and that this bug started happening with iOS 14.2.

There is also a long bug thread in the Unity forums where users using "ARFoundation" and iOS 14.2 or 14.3 are experiencing what appears to be another symptom of this issue (see link in the GitHub issue above, since Apple forums forbids me from pasting the direct link here).

This smells a lot like a bug in dispatch_async_f() that was introduced in iOS 14.2 when ARKit is also in play.

for which the only explanation is that the "dispatch function"
specified to dispatch_async_f is never called back.

I can’t speak to the ARKit side of this but, from a Dispatch perspective, there are two common causes for this:
  • You’re using the .background QoS and the device is in a condition that disallows that QoS (low power mode, extremely hot, and so on).

  • You’ve queued too much work concurrently, which has run Dispatch out of worker threads.

See this post for more info about the latter.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
@eskimo Thank you for your thoughts on this. The dispatch queue that I am using is not the global dispatch queue, but rather one created via the following code (link):

Code Block c++
dispatch_queue_t queue = dispatch_queue_create("com.google.firebase.firestore.query", DISPATCH_QUEUE_CONCURRENT);


The QoS of the dispatch queue is never changed so I'm assuming it gets an initial value of DISPATCH_QUEUE_PRIORITY_DEFAULT; therefore, I don't think that it should not be subject to the situations that you mentioned that would cause starvation had its QoS been demoted to DISPATCH_QUEUE_PRIORITY_BACKGROUND.

Also, the load on this queue is relatively light. In my specific scenario, its queue length never exceeds 1.

I'm going to take a look at the WWDC talks you linked to; however, there are several bug reports across the internet that report problems with dispatch queue callbacks ceasing to fire in iOS 14.2 and 14.3 when ARKit is involved.

The dispatch queue that I am using is not the global dispatch queue,
but rather one created via the following code

Right, which is a concurrent queue, which is something you should generally try to avoid.

its queue length never exceeds 1.

So you can replace it with a serial queue and rule out that part of the problem, right?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"