-
-
Notifications
You must be signed in to change notification settings - Fork 877
Closed
Labels
type:bugImpaired feature or lacking behavior that is likely assumedImpaired feature or lacking behavior that is likely assumed
Milestone
Description
I have two PFObject subclasses A and B. A has an array of pointers to B, and B has a pointer to A.
Sometimes my app will fire off two save operations for A in rapid succession, and this will result in a deadlock. Here's where the deadlock occurs when saving an instance of A that references two B instances:
On thread 1:
- A iterates through the remaining items to save in PFObject#_deepSaveAsyncChildrenOfObject:withCurrentUser:sessionToken:. Those remaining items are a collection in the order B,A,B. It encounters A in the enumeration and calls canBeSerializedAfterSaving:withCurrentUser:error
- A synchronizes on its lock in PFObject#canBeSerializedAfterSaving:withCurrentUser:error
- A enumerates through its keys, and eventually comes to its reference to B.
- In PFObject#canBeSerializedAsValue:afterSaving:error:, the object ID for B is accessed.
- B synchronizes with its lock when it access its state.
- So now we have synchronized locks on this thread in the order A,B
Meanwhile, on thread 2:
- A iterates through the remaining items to save in PFObject#_deepSaveAsyncChildrenOfObject:withCurrentUser:sessionToken:. Those remaining items are a collection in the order B,A,B. It encounters B in the enumeration and calls canBeSerializedAfterSaving:withCurrentUser:error
- B synchronizes on its lock in PFObject#canBeSerializedAfterSaving:withCurrentUser:error
- B enumerates through its keys, and eventually comes to its reference to A.
- In PFObject#canBeSerializedAsValue:afterSaving:error:, the object ID for A is accessed.
- A synchronizes with its lock when it access its state.
- So now we have synchronized locks on this thread in the order B,A
BAM! Classic deadlock
One thread has lock in the order A,B, and the other has locked in the order B,A
Two possible ideas for fixes:
- Sort the collection of remaining objects in _deepSave...
- Limit the synchronization scope in canBeSerializedAsValue:afterSaving:error:, perhaps by making a copy of the dictionary and then proceeding. It seems risky to be synchronizing that entire block of code there because it could be doing all kinds of recursive accesses that could result in this deadlock.
Metadata
Metadata
Assignees
Labels
type:bugImpaired feature or lacking behavior that is likely assumedImpaired feature or lacking behavior that is likely assumed