|
|
@@ -16,6 +16,13 @@
|
|
|
something in dispatch_sync
|
|
|
|
|
|
*/
|
|
|
+
|
|
|
+/**
|
|
|
+ * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses.
|
|
|
+ * This in turn is used for deadlock detection by seeing if inDatabase: is called on
|
|
|
+ * the queue's dispatch queue, which should not happen and causes a deadlock.
|
|
|
+ */
|
|
|
+static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
|
|
|
|
|
|
@implementation FMDatabaseQueue
|
|
|
|
|
|
@@ -67,6 +74,7 @@ - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
|
|
|
_path = FMDBReturnRetained(aPath);
|
|
|
|
|
|
_queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
|
|
|
+ dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
|
|
|
_openFlags = openFlags;
|
|
|
}
|
|
|
|
|
|
@@ -129,6 +137,11 @@ - (FMDatabase*)database {
|
|
|
}
|
|
|
|
|
|
- (void)inDatabase:(void (^)(FMDatabase *db))block {
|
|
|
+ /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue
|
|
|
+ * and then check it against self to make sure we're not about to deadlock. */
|
|
|
+ FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
|
|
|
+ assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
|
|
|
+
|
|
|
FMDBRetain(self);
|
|
|
|
|
|
dispatch_sync(_queue, ^() {
|