Skip to content

Commit e8b9c53

Browse files
Fixed deadlock in -collectDirtyChildren:
By no longer holding a lock while recursing, we allow other threads who may be waiting on the current object to progress before iterating to children of the object, solving some of the deadlocks that we've seen in issues #11, #61, and #299. This does not necessarily fix the above issues, as we probably still have similar deadlocks elsewhere in the codebase. cc @grantland
1 parent 0a0f856 commit e8b9c53

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

Parse/PFObject.m

+12-10
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ + (void)collectDirtyChildren:(id)node
241241

242242
} else if ([node isKindOfClass:[PFObject class]]) {
243243
PFObject *object = (PFObject *)node;
244+
NSDictionary *toSearch = nil;
244245

245246
@synchronized ([object lock]) {
246247
// Check for cycles of new objects. Any such cycle means it will be
@@ -266,18 +267,19 @@ + (void)collectDirtyChildren:(id)node
266267
// Recurse into this object's children looking for dirty children.
267268
// We only need to look at the child object's current estimated data,
268269
// because that's the only data that might need to be saved now.
269-
[self collectDirtyChildren:object->_estimatedData.dictionaryRepresentation
270-
children:dirtyChildren
271-
files:dirtyFiles
272-
seen:seen
273-
seenNew:seenNew
274-
currentUser:currentUser];
275-
276-
if ([object isDirty:NO]) {
277-
[dirtyChildren addObject:object];
278-
}
270+
toSearch = [object->_estimatedData.dictionaryRepresentation copy];
279271
}
280272

273+
[self collectDirtyChildren:toSearch
274+
children:dirtyChildren
275+
files:dirtyFiles
276+
seen:seen
277+
seenNew:seenNew
278+
currentUser:currentUser];
279+
280+
if ([object isDirty:NO]) {
281+
[dirtyChildren addObject:object];
282+
}
281283
} else if ([node isKindOfClass:[PFFile class]]) {
282284
PFFile *file = (PFFile *)node;
283285
if (!file.url) {

0 commit comments

Comments
 (0)