CoreData: Private-queue context occasionally skips persistence controller's barrier queue
| Originator: | cwilliams | ||
| Number: | rdar://23223338 | Date Originated: | 22-Oct-2015 |
| Status: | Open | Resolved: | |
| Product: | iOS SDK | Product Version: | |
| Classification: | Crash | Reproducible: | Sometimes |
Summary: We're getting a fair number of crashes due to issues with synchronized access to NSPersistentStoreCoordinator's NSSQLConnection. It looks like there's a situation where the coordinator chooses not to use the barrier queue, despite it being necessary (See Thread 9 in crash). When the main queue context attempts to do a fetch at the same time, NSQLConnection checks _statement and throws 'NSInternalInconsistencyException', reason: 'statement is still active' because the background context's fetch is still happening. Our setup is kinda weird. We have two contexts in a parent/child relationship and a third context, all sharing the same persistence coordinator. I'm not clear on how relevant that is to the issue. Gritty investigation details: It looks like you're using pthread data to keep track of which queues the thread has gone through, and under some circumstance this doesn't get cleaned up correctly. In the case of the crash I'm seeing, it looks like [what I'm assuming is] an anti-deadlock mechanism incorrectly believes it's already past the persistence coordinator's barrier and starts executing code that uses the NSSQLConnection immediately. My suspicion is there's some exception that gets caught, which leads to an instance of gutsOfBlockToNSPersistentStoreCoordinatorPerform not getting executed to completion. Unfortunately it doesn't seem to be on our side, as none of our @catch blocks appear to fire before the crash. Steps to Reproduce: The actual setup for this is probably pretty convoluted, but basically imagine you have our codebase, which has a few contexts: a parent, a child, and a non-nested one. 1. <Have Our Setup> 2. Schedule a timer to run a ton of UI updates using the child thread 3. Schedule a timer to run a ton of fetches on the non-nested context 4. Wait a few minutes 5. <Something happens> 6. Non-nested context gets its fetch request executed without synchronizing with the barrier queue 7. Child context correctly uses barrier queue, despite it having been rendered symbolic in Step 6 5. Crash when the child context attempts to use the SQLConnection at the same time as the non-nested context. Expected Results: The coordinator's barrier queue is used correctly. Actual Results: The coordinator's barrier queue can be bypassed despite not having synchronized with it previously. Version: iOS 8.4-9.0.1, iOS SDK 8-9 Notes: Configuration: Any device
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!