随着我们的应用越来越大,我们开始注意到XMPPFramework CoreDataStorage的scheduleBlock:方法中的死锁,如下所示:
- (void)scheduleBlock:(dispatch_block_t)block
{
// By design this method should not be invoked from the storageQueue.
//
// If you remove the assert statement below, you are destroying the sole purpose for this class,
// which is to optimize the disk IO by buffering save operations.
//
NSAssert(!dispatch_get_specific(storageQueueTag), @"Invoked on incorrect queue");
//
// For a full discussion of this method, please see XMPPCoreDataStorageProtocol.h
//
// dispatch_Async
// ^
OSAtomicIncrement32(&pendingRequests);
dispatch_async(storageQueue, ^{ @autoreleasepool {
block();
[self maybeSave:OSAtomicDecrement32(&pendingRequests)];
}});
}
虽然它发生在一个框架内,但我确实认为这个问题与整个GCD讨论有关,因为它只发生在非常特殊的情况下(在我们的例子中,它首先仅通过压力测试报告)和提到的代码以上情况适用于绝大多数情况。
我们注意到,如果在短时间内多次调用此方法,突然间会产生死锁。正如我们的日志指出的那样,其中一个调用输入dispatch_async,但从不#34;留下它"。以下内容只会增加" pendingRequests"变量"击中"阻止的storageQueue,永远不会被执行。
这个问题似乎不容易重现。在我们的测试中,我们每秒启动2到5次调用方法。死锁随机发生在5到50秒之间。根据每秒的调用次数和其他调整,你可以将其推迟到150秒左右,但它不能解决问题(死锁仍然会发生,只是稍后)。值得一提的是,对这种方法的调用来自不同的线程,包括mainThread。
由于这个问题非常难以通过常见手段重现,至少在我们的应用中,它不应该是评论家。但是,我们现在担心这可能会随机发生#34;为我们的用户。我们感觉不安全"用这种方法,特别是在缩放方面。
所以,我们想开始并加入围绕这个的进一步讨论,这是GCD的一个非常传统的用法。如果有人发现该方法可能存在失败点,或者如果有人想提出不同的方法或指出某些不同的做法,那么一切都会非常受欢迎。
编辑1 - 这是一个显示死锁的日志。我对这些行进行了编号,以便于讨论。你会注意到一切都顺利到第30行。在那里,一个块在XMPPMessageArchivingCoreDataStorage中安排,来自主线程。紧接着,另一个块被安排,现在来自线程11.这些都不会被执行。在第33和35行,您会注意到队列开始构建,但存储线程永远不会被释放",因此不会执行任何排队操作。
1 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Event #30 started
2 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
3 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
4 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 0 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
5 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
6 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
7 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]> / Schedule Block Thread: <NSThread: 0x15e972c30>{number = 18, name = (null)}
8 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Will Schedule Block -> 1 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d6bf4a0>{number = 7, name = (null)}
9 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
10 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 1 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
11 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 0 pending requests - Storage Queue :<OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]>
12 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Will Schedule Block -> 1 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
13 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
14 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 1 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
15 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
16 - Oct 19 16:45:18 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 0 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
17 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
18 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
19 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 0 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
20 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d6bf4a0>{number = 7, name = (null)}
21 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Event #31 started
22 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Will Schedule Block -> 1 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
23 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
24 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]> / Schedule Block Thread: <NSThread: 0x15e972c30>{number = 18, name = (null)}
25 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 0 pending requests - Storage Queue :<OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]>
26 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
27 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 1 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
28 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Schedule Block Thread: <NSThread: 0x15e9caaf0>{number = 16, name = (null)}
29 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Did Finish Schedule Block -> 0 pending requests - Storage Queue :<OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]>
30 - Oct 19 16:45:19 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
31 - Oct 19 16:45:20 Ronaldo-Juniors-iPhone: Will Schedule Block -> 1 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15eaf8a50>{number = 11, name = (null)}
32 - Oct 19 16:45:20 Ronaldo-Juniors-iPhone: Event #32 started
33 - Oct 19 16:45:20 Ronaldo-Juniors-iPhone: Will Schedule Block -> 2 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
34 - Oct 19 16:45:20 Ronaldo-Juniors-iPhone: Will Schedule Block -> 0 pending requests - Storage Queue: <OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]> / Caller Thread: <NSThread: 0x15d51a0a0>{number = 1, name = main}
35 - Oct 19 16:45:20 Ronaldo-Juniors-iPhone: Will Schedule Block -> 3 pending requests - Storage Queue: <OS_dispatch_queue: XMPPMessageArchivingCoreDataStorage[0x15d5c8c90]> / Caller Thread: <NSThread: 0x15eaf8a50>{number = 11, name = (null)}
36 - Oct 19 16:45:20 Ronaldo-Juniors-iPhone: Dispatched Scheduled Block at storage queue <OS_dispatch_queue: XMPPRosterCoreDataStorage[0x15d5c7ec0]> / Schedule Block Thread: <NSThread: 0x15eaf8a50>{number = 11, name = (null)}