Fault exception trashes a register causing a crash in [NSInvocation invoke]
I have an NSOperation
which fetches some objects from a core data persistent store and sums up a few totals. Sometimes an object is deleted while the operation in in progress, so a core data fault exception occurs. I try/catch the exception while summing to ignore it because I just want to skip objects that cannot be faulted in.
However, when one of these fault exceptions occurs (and I swallow it) there is a crash after the invocation开发者_如何学C returns in [NSInvocation invoke]
. It's a bad memory access when dereferencing the value in r10 which according to GDB on a successful run points to one of these:
(gdb) x 0x38388348
0x38388348 <OBJC_IVAR_$_NSInvocation._retdata>: 0x00000008
If a fault exception occured a value of 0x02 is in the register which causes the crash.
A quick google search tells me that r10 should be saved by the callee, meaning it is not being restored by whatever code is changing it when this exception occurs.
Can anybody explain this? I'm not an expert when it comes to these kinds of low-level details
I think you're asking the wrong question. A Cocoa application should never throw an exception under normal operation. You need to address the cause of that exception before doing anything else.
You should not be accessing a single managed object context from multiple threads, or if you are you need to lock it very carefully. Multithreaded access to one context is highly dangerous, and can lead to the kind of behavior you are observing. From the "Multi-Threading with Core Data" section of the Core Data Programming Guide:
If you want to work with a managed object across different threads, you must lock its context (see NSLocking). If you try to pass actual objects, share contexts between threads, and so on, you must be extremely careful about locking (and as a consequence you are likely to negate any benefit you may otherwise derive from multi-threading). Working with a managed object across different threads is therefore strongly discouraged, as described in “General Guidelines.”
It is recommended that you use a separate managed object context for your background thread (with the same persistent store and managed object model), and do all of the reads you need for your summation operation there.
精彩评论