Skip to content

Instantly share code, notes, and snippets.

@steipete
Last active December 21, 2018 15:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save steipete/aa71bfd6fbd02de9e95ae2a92313e08e to your computer and use it in GitHub Desktop.
Save steipete/aa71bfd6fbd02de9e95ae2a92313e08e to your computer and use it in GitHub Desktop.
This fails in iOS 9, but passes for iOS 10/11. What changed around serial/concurrent dispatch queues in iOS 10 so that this now works. Or rather, why does this not work in iOS 9?
- (void)testDispatchConcurrentExecutionWithNamedQueuesRaw {
let expectation = [self expectationWithDescription:@"Concurrent execution must happen"];
let semaphore = dispatch_semaphore_create(0);
// global queue, concurrent
let attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, 0);
let defaultQueue = dispatch_queue_create("com.pspdfkit.default-concurrent", attributes);
// serial sub-queues that dispatch to concurrent queue
let queue1 = dispatch_queue_create("com.pspdfkit.queue1", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue1, defaultQueue);
let queue2 = dispatch_queue_create("com.pspdfkit.queue2", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue2, defaultQueue);
// This only passes if the blocks dispatched to the global queue run concurrently.
// Surprisingly, this works on iOS 10/11 but fails on iOS 9.
dispatch_async(queue1, ^{
// dispatch second async operation which needs to start concurrently
dispatch_async(queue2, ^{
dispatch_semaphore_signal(semaphore);
});
// we cannot lock again, first have to unlock
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[expectation fulfill];
});
[self waitForExpectations:@[expectation] timeout:10];
}
@steipete
Copy link
Author

steipete commented Feb 5, 2018

This is the result from a few hours of deadlock-hunting on our CI tests for iOS 9 specifically. (only happened sometimes, timings).

It seems that using let defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); instead of our own custom global queue does make things pass on iOS 9, so I assume the DISPATCH_QUEUE_CONCURRENT behaviour of custom queues changed and was buggy/did not behave as the documentation said on iOS < 10.

@steipete
Copy link
Author

steipete commented Feb 6, 2018

Twitter yielded no results, opened a DTS.

@steipete
Copy link
Author

steipete commented Feb 6, 2018

Seems this indeed was a bug in iOS 9 and got fixed: https://twitter.com/pedantcoder/status/960912480665968640

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment