I'm using Apple's concurrency core data debugger.
-com.apple.CoreData.ConcurrencyDebug 1
From time to time I got __Multithreading_Violation_AllThatIsLeftToUsIsHonor__
, even I'm almost sure threading is not violated.
This is part of code where exception occurs (code is part of protocol that extends NSManagedObject):
public static func find(arrayBy predicate: NSPredicate, sort: [NSSortDescriptor] = [], limit: Int? = nil) -> [Self] {
let fetchRequest = NSFetchRequest<Self>(entityName: "\(Self.self)")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = sort
do {
return try Context.current.fetch(fetchRequest) // Exception!!!
} catch let error {
Logger.fatal("Failed to perform fetch: \(error)")
return []
}
}
Code is executed within context's perform:
block.
Here is thread information:
and debuger info to confirm that perform is executed on the right NSManagedContext:
(lldb) po Context.current
<StoreContext: 0x7f854b556610>
Entity name is extracted successfully:
po fetchRequest.entityName!
"Position"
Predicate is constructed of pure String objects (no managed objects used at all):
(lldb) po fetchRequest.predicate!
ANY employees.company.id == "282372"
Sort descriptors are not used at all in this case:
po fetchRequest.sortDescriptors!
0 elements
Limit is completely ignored.
What am I missing? Does anyone has any idea what can be wrong here?
Edit:
To clarify, Context.current
is set just before dispatching the block:
Context.current = managedObjectContext
managedObjectContext.performAndWait {
//...
}
You can see on the screenshot that Thread 13
is running on Queue: NSManagedObject 0x7f854b556610 (serial)
. Also, when exception occurs Context.current
returns <StoreContext: 0x7f854b556610>
. By looking at the memory address it's easy to conclude block is executing on the right queue.
Storing the "current" background context in a global state is a bad practice. I can't point out where exactly in your code it is messing up, but unexpected things can happen with global state when multithreading is involved. Change your find
function to accept a context
as a parameter. This will avoid using any global state and is will likely fix your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With