Why is this dispatch_sync() call freezing? Why is this dispatch_sync() call freezing? multithreading multithreading

Why is this dispatch_sync() call freezing?


For the second part of your question regarding the hint on the freeze:

When calling dispatch_sync on a queue, always verify that this queue is not already the current queue (dispatch_get_current_queue()). Because dispatch_sync will queue your block on the queue passed as the first parameter, and then will wait for this block to be executed before continuing.

So if the dispatch_get_current_queue() and the queue on which you enqueue your block are the same, namely the main queue in your case, the main queue will block on the call to dispatch_sync until… the main queue as executed the block, but it can't, as the queue is blocked, and you have a beautiful deadlock here.

One solution ([EDIT] up until iOS6):

dispatch_queue_t main = dispatch_get_main_queue();dispatch_block_t block = ^              {                  [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];              };if (dispatch_get_current_queue() == main)  block(); // execute the block directly, as main is already the current active queueelse  dispatch_sync(main, block); // ask the main queue, which is not the current queue, to execute the block, and wait for it to be executed before continuing

[EDIT] Be careful, dispatch_get_current_queue() is only to be used for debugging purposes and never in production. In fact, dispatch_get_current_queue is deprecated since iOS6.1.3.

If you are in the specific case of the main queue (which is associated with the main thread only), you may instead test [NSThread isMainThread] as suggested by @meaning-matters.


By the way, are you sure you need to dispatch_sync in your case?I guess sending your notification a bit later, avoiding to block until it has been sent, is acceptable in your case, so you may also consider using dispatch_async (instead of using dispatch_sync and needing the queue comparison condition), which would avoid the deadlock issue too.


dispatch_get_current_queue() is deprecated starting from iOS 6, and dispatch_get_current_queue() == dispatch_get_main_queue() was found to be false while on main thread on iOS 6.1.3.

In iOS 6 and beyond simply do:

dispatch_block_t block = ^{    <your code here>};if ([NSThread isMainThread]){    block();}else{    dispatch_sync(dispatch_get_main_queue(), block);}