Browse Source

Merge pull request #224 from mikeash/master

Add a deadlock check to -[FMDatabaseQueue inDatabase:]
August "Gus" Mueller 12 years ago
parent
commit
018a7b81dd
1 changed files with 13 additions and 0 deletions
  1. 13 0
      src/FMDatabaseQueue.m

+ 13 - 0
src/FMDatabaseQueue.m

@@ -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, ^() {