2

I've run into an issue I had never seen before. I never thought it might exist. I'm using DFCache library and in a certain moment dispatch_async using global queue doesn't execute block.

- (void)cachedObjectForKey:(NSString *)key completion:(void (^)(id))completion {
if (!key.length) {
    _dwarf_cache_callback(completion, nil);
    return;
}
id object = [self.memoryCache objectForKey:key];
if (object != nil) {
    _dwarf_cache_callback(completion, object);
    return;
}

NSLog(@"Before calling async %d queue %p", [NSThread isMainThread], _processingQueue);

dispatch_async(_processingQueue, ^{
     NSLog(@"Block called");

    @autoreleasepool {


        id object = [self _cachedObjectForKey:key];
        _dwarf_cache_callback(completion, object);
    }
});

}

this is how this queue was created:

 _processingQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

the queue is never used in any other place. This is not my code. This is the code of DFCache library. But there's something in my code affecting the queue because it stops working always in a particular moment. I load, save, load, save, load and ... the block is not called. But I can't understand why. I need to know what may cause the block to be not called on dispatch_async. My code is so big and complex so I don't post it here. What I need is a hint. What specific reason might cause this behaviour? Did you ever see dispatch_async not calling its block on a global queue? What was causing that?

2
  • Obliviously you need to check all other cases instead of suspecting dispatch. Commented Feb 11, 2015 at 9:40
  • 2
    The queue may be locked, you can pause the program and go to debug navigator to check if any thread is locked. Commented Feb 11, 2015 at 9:44

3 Answers 3

3

If you saw "Before calling async ..." in the log message but no "Block called", One possible situation is that all threads were blocked in global queue.

For example, the following code should print "Block called" infinitely, but not.

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(q, ^{
    while (YES) {
        dispatch_async(q, ^{
            NSLog(@"Block called\n");

            // BLOCK THE THREAD
            while (YES)
                ;
        });
    }
});

The system prepared a thread pool for global queue. The number of threads in the pool may vary depending on runtime status, anyway, the number of threads are limited. Eventually, all threads would be blocked by the infinite loop.

Thus, your code might have some deadlock, infinite loop, or sort of things blocking global queue threads.

Sign up to request clarification or add additional context in comments.

Comments

0

The reason would be like the method(cachedObjectForKey) is returning before the execution of dispatch_async. we can see that

if (object != nil) {
  _dwarf_cache_callback(completion, object);
   return; // this might be the reason for not calling of dispatch_async
}

there is one more return in your code, if key.length is not present.

Hope this helps

1 Comment

no, it's not. of course I checked that. It is indeed dispatch_async not calling its block. The function is not returning too early. I see it through NSLog
0

In my case, we updated a bunch of third party libraries and this started happening. Pausing the app and analysing the threads, there were a couple instances of TapStream 'internal threads' waiting. I disabled TapStream and this problem disappears. It still doesn't make sense to me why its internal threads would block the global queue...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.