I make some non-essential changes to the database in a background thread (shortly after app launch), and then merge them into the main context. The background thread can end up making a lot of changes, but I don't want the context save to trip up over some validation errors or some inscrutable Core Data exception in this background processing; especially since I use iCloud with Core Data, users can end up with nilled-out relationships and what not. I just want the app to keep running instead of throwing an exception and quitting.
In this case, does it make sense to have a #try-#catch block around the context save? Are there any performance or memory management issues with doing this?
Something like this:
#try {
[context performBlockAndWait: ^{
NSError *error = nil;
if ([context save:&error]){
NSLog(#"Child context saved");
[context.parentContext performBlockAndWait:^{
NSError *parentError = nil;
if ([context.parentContext save: &parentError]){
NSLog(#"Parent context saved");
}
}];
}
}];
} ....
My app ships to thousands of customers, so it would be great to know before-hand if this could cause more problems than it solves.
What exceptions are being thrown?
Since -[NSManagedObjectContext save:] uses the NSError out-parameter pattern, I would generally expect it NOT to throw. However, the general pattern in Cocoa is that exceptions are "death" and not considered recoverable.
There are places in various system frameworks that throw and catch exceptions (which you can see by setting an exception-throw breakpoint in the debugger) -- I'm looking at you Cocoa bindings -- but generally speaking if an exception bubbles up to your app's code, you're already "dead in the water."
Are there any performance or memory management issues with doing this?
These days, the performance penalty for a #try/#catch/#finally is pretty minimal (this wasn't always the case). There are memory management implications to be sure (which is probably why exceptions are generally "death" on this platform.) If you're using ARC and exit a scope by way of an exception being thrown, retains taken by ARC are not released. As described here:
The standard Cocoa convention is that exceptions signal programmer
error and are not intended to be recovered from. Making code
exceptions-safe by default would impose severe runtime and code size
penalties on code that typically does not actually care about
exceptions safety. Therefore, ARC-generated code leaks by default on
exceptions, which is just fine if the process is going to be
immediately terminated anyway. Programs which do care about recovering
from exceptions should enable the option.
In short, there's probably no point in wrapping a context save operation in a #try/#catch block.
Related
We have 2 applications, the first one is VCL project, the other is a windows service.
In the VCL project we do:
try
except
on E: Exception do
// do something with E.Message
end
but in the windows service (which uses several threads) we use:
try
except
// do something with Exception(ExceptObject).Message
end
The information I got from my coworkers is that "We must use ExceptObject in threads and E: Exception in applications that use GUI". But I couldn't find anything regarding this.
I found an example here http://edn.embarcadero.com/article/10452 where it uses an instance variable to store the exception and it uses the ExceptObject, but gives no explanation why.
Is this ExceptObject even thread-safe (since it comes from the unit 'System')?
So what is the right way to handle exceptions in Delphi and why is there more than one way to do it?
There is no right way for exception handling. There is just one way. What might confuse you could be dealing with the exception object which is created, and which causes an exception to raise, but whose lifetime is the most important for you here.
In general, there's only two ways of dealing with those exception objects. Either you let them alive beyond the exception block scope and release them by yourself or let them free by the RTL when the exception block ends.
But to answer what I guess you've asked. Exception class isn't thread safe. And, your coworkers were wrong as no one is forced to use specific exception handling in threads. These rules are the same for all threads created by the process, no matter what. Just, those exception objects can be unstable within exception blocks:
1. Get the current exception object from the ExceptObject
The ExceptObject returns the current exception object. In practice, it may cause this; if you store such object reference into a variable inside an exception handler block and another exception will get raised within such block, that stored instance may become invalid. Which is quite unsafe.
But it doesn't mean you could not take a reference of such object and pass it to another thread by using some synchronization mechanisms (since it's not a thread safe class) and work with it there. You just need to take care that no other exception will be raised because that would invalidate the previously stored object so as you must take care of staying inside the exception handler from the caller's point of view and you must use a kind of thread synchronization mechanism.
So actually working with the exception object acquired from an on expression can be more stable than using ExceptObject. But the same rules applies here as well; you'd need to synchronize the object instance from the on expression with another thread (since it's not a thread safe class), but in such case, object acquired from the on expression won't get changed unlike the ExceptObject one can be within a certain exception block.
2. Retain exception object by using AcquireExceptionObject
The AcquireExceptionObject function allows you to keep the exception object alive even out of the exception block.
For an exception handling when speaking about thread synchronization, I'd suggest you using the AcquireExceptionObject function which makes the exception object free to consume, even after the exception block ends. For you that brings the only responsability, free such acquired object by calling the ReleaseExceptionObject procedure or raising the exception by this object again.
Victoria is absolutely correct.
Personally, I have a strong preference for this idiom:
try
...
except
// IO error
On E : EInOutError do
ShowMessage('IO error : '+E.Message);
// Division by zero
On E : EDivByZero do
ShowMessage('Div by zero error : '+E.Message);
// Catch other errors
else
ShowMessage('Unknown error');
end;
To elaborate:
Victoria said "There is no right way for exception handling. There is just one way." That's absolutely correct.
The advice you got about "use one syntax for threads, and the other for GUIs" is simply wrong. There is no "different syntax" for "threads" vs. "GUI". That's nonsense :(
I prefer using on : MyExceptionType in an exception block.
I also prefer to differentiate different exception types, whenever/wherever possible.
The example you cited, http://edn.embarcadero.com/article/10452, deals with how to avoid a possible access violation if you don't handle the exception within that particular thread. Saving the exception instance in a member variable helps mitigate this problem.
The following link might help clarify:
http://www.delphibasics.co.uk/Article.asp?Name=Exceptions
My approach so far has been something like this:
1- A main context initialized like so:
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model];
if(![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
DDLogModel(#"Unresolved error %#", error.localizedDescription);
return;
}
self.context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.context.persistentStoreCoordinator =_persistentStoreCoordinator;
2- Then, as I go about creating core data objects or modifying their relationships concurrently:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSManagedObjectContext *tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
tempContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
// Do stuff
[tempContext save:nil];
});
3- And finally, the main context merge via the NSManagedObjectContextDidSaveNotification
However, I've recently seen a different approach where for step 2, they instead create a context with NSPrivateQueueConcurrencyType, make it a child of the main context, and do any work by means of -performBlock:
Is this last approach concurrent by default (even without explicitly dispatching it as such)? Or what's the advantage over the approach I explained?
Another thing that threw me off is that even though the contexts have parentContext and persistentStoreCoordinator properties, it appears that setting the latter implies one cannot set the former. That is, a context with a persistent store coordinator actually has that store coordinator as it's parent context?
UPDATE:
Another interesting thing is that with the approach I described above (using GCD), everynow and then when I do [tempContext save:] I get a weird behaviour: No error is returned (assuming I do pass in an NSError object, unlike in the example), but if I set the generic Objective-C exception pointer on, the background thread does stop there, as if there was an exception. However, if I continue the app does not crash and keeps going and the main moc seems to be just fine.
You are right. performBlock will automatically perform the work in the background. In some cases it might make sense to use the current thread (main or background), in which case you can use performBlockAndWait. Using child contexts is the recommended approach.
I suppose your setup could work just as well. I guess the advantage of using a child context lies in a more structured approach of saving, i.e. "pushing up" saves into the parent context. Only the parent context will actually touch the persistent store, so this is better in terms of thread safety.
Your last question is not clear. A context can only have a context as its parent context, not a persistent store coordinator. However, what might be confusing you is that prior to iOS 5 there was only a "Parent Store", and with the introduction of child contexts it could be replaced optionally by a parent context. Read all about it here.
#property (nonomic,retain) CMMotionManager *motionManager; //delcare as a property.
motionManager = [[CMMotionManager alloc] init]; //init it.
motionManager.accelerometerUpdateInterval = 0.2f;
All below perform in a thread(not main thread).
-(void)handle{
[motionManager startAccelerometerUpdates];
while (1) {
CMAcceleration acceleration = motionManager.accelerometerData.acceleration;
NSLog(#"%f %f %f",acceleration.x,acceleration.y,acceleration.z);
sleep(0.5);
}
}
When I run the app in Xcode -> Instruments, I found the Living Memory increase uninterruptly,
until the app recieved memory warming and killed by system.
I try to relase the accelerometerData in while block. but make no effect. motionManager.accelerometerData release];
I don't wish to use startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData *accelerometerData,NSError *error), becuase I want to run it in background,and this block make no function when the app be suspended.
Can anyone help me?
screenshot image:http://img.blog.csdn.net/20130702120140593
Are you using ARC? You should use it.
You must also make sure your bakground thread has an autorelease pool in place. The syntax for creating an autorelease pool with ARC enabled is #autorelease { ... } and the syntax without ARC is NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ... [pool release];.
Apple has excellent documentation on how autorelease pools work. One is created automatically for the main thread but you must manually create it for background threads. You need to spend a couple of hours learning how it works, it's mandatory learning for any obj-c programmer.
Without seeing all your code, I can't tell you how it needs to work... but most likely the block or method you create the thread with needs it's contents wrapped in an autorelease pool and also the contents of your while loop needs a second autorelease pool.
EDIT: now that I've seen your code, you here is an example of how #autoreleasepool must be used to avoid leaking memory. I added line 6 and 23 to this code: https://gist.github.com/abhibeckert/5907754
I haven't tested, but that should solve your problem. It will definitely leak memory without those autorelease pools.
Basically if you have a background thread or long while loop, each needs to have it's own autorelease pool. I recommend reading this: http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
I am going crazy trying to figure this out. I am working on an application that is syncing up data from the webserver. There is a background thread that is pulling data from the server to the application. At the same time I am making changes to the UI. The values changed on UI are being saved to core data in foreground.
Through out the application I have one managedObjectContext that I fetch from the app delegate every time I create a fetchController . App delegate code
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
Now the problem is I am getting error while trying to save the context. The errors are happening randomly in the code. I am saving the context as soon as I am making change to any entity. Also I have two relationships each in each entity one to its child that is one to many and one to its parents that is to - one. All relationship have appropriate inverse.
I think I am doing something conceptually wrong over here by mentaining one context. Could you please advice how I should manage context in a situation where both background and foreground threads are reading and writing to the coredata. Thanks.
Managed object contexts are not thread safe, so if you use the same one on more than one thread without considering concurrency-- you're going to have major problems. As in, crashing and/or data loss and maybe even data corruption. There are a couple of ways to deal with this:
Use one of the queue concurrency types when creating the context-- see docs for initWithConcurrencyType:. Then, whenever you access the data store, use either performBlock: or performBlockAndWait: to synchronize access.
Create a new managed object context for the background thread. Use NSManagedObjectContextDidSaveNotification and mergeChangesFromContextDidSaveNotification: to keep multiple contexts synchronized.
But whatever you do, do not just use one managed object context on more than one thread.
I'm working on various C++ COM DirectShow filters called from C# clients via COM interop. There's little use of C++ exceptions in the code. The main exception is operator new which can throw bad_alloc exceptions.
Is there a clean way of handling bad_alloc exceptions in a way which can be caught by the C# client?
Could a new handler throw some an SEH exception that could be caught by COM interop clients?
Or would it be better to link with the backwardly-compatible non-throwing version of new in Visual Studio libraries and check every allocation?
One tedious alternative is to write a try/catch for hundreds of COM entry points which doesn't seem worthwhile since bad_alloc exceptions are rarely recoverable.
The DirectShow base classes generally check for null returns from operator new as they seem to have been written for earlier versions of Visual C++ that didn't throw bad_alloc exceptions.
You'll have to catch the exception and return E_OUTOFMEMORY. Only do this for large allocations, there's little point in trying to stumble on when small ones fail. Nothing good ever happens after the program has consumed 2 gigabytes of virtual memory, you might as well let it die. Large allocations are likely to fail due to address space fragmentation, there can still be lots of unused space left.
The COM API contract requires that you not allow ANY C++ exceptions to flow across the COM API boundry.
That means you need to catch all C++ exceptions and turn them into HRESULTs before they leave your COM API.
You might be able to get away with this in some rare circumstances (if, for instance you can guarantee that the COM client and COM server were built with the same version ofthe compiler), but there are a myriad of circumstances that can mess this up (for instance the COM server lives behind a proxy/stub (which can happen if you have multiple apartments or if the server is out-of-proc), or if the COM server is being called from another language like one of the CLR languages).
In general, something like:
catch (...)
{
return E_FAIL;
}
at the end of each of your COM APIs will go a long way to improve the robustness of your code.
Yes, wrap all methods into big try-catch:
#define BEGIN_COM_METHOD try {
#define END_COM_METHOD \
} catch( const std::bad_alloc& ) {\
return E_OUTOFMEMORY;\
} catch( ... ) {\
return E_FAIL;\
}\
return S_OK;
HRESULT YourComClass::SomeMethod()
{
BEGIN_COM_METHOD
DoUsefulStuff();
END_COM_METHOD
}
Using this you no longer propagate exceptions through the COM boundary.
Thanks for the answers. I can see why C++ exceptions can't reliably pass a COM boundary. What does the COM contract have to say about structured exceptions flowing across a COM boundary though?
How about the following technique which turns operator new failures into structured exceptions? Or are there good reasons why this is a bad idea?
void __cdecl OutOfMemoryHandler()
{
RaiseException(STATUS_NO_MEMORY, 0, 0, NULL);
}
std::set_new_handler(OutOfMemoryHandler);
I notice that ATL can do a similar trick in AtlThrow of handling E_OUTOFMEMORY HRESULT by raising STATUS_NO_MEMORY structured exceptions though the behaviour depends on the preprocessor symbols defined.
In native code this technique would also suggest that the /EHa compiler option heeds to set so that stack unwinding happens and destructors get called for structured exceptions. I can see this would cause a performance hit if I were using a lot of try/catch clauses but in the current context I'm using no try/catch clauses at all. Would I still get a performance hit from using /EHa?
Structure exception handling compiler settings may be a good idea in any case. Another stack overflow poster describes a nasty bug where a C++ object wrapped critical section (commonly used in the DirectShow base classes) failed to unlock when a structured exception was raised in a called module. The compiler settings were set for C++ exception handling only and the object wrapping the critical section did not get destroyed when the structured exception was raised and deadlock happened later on.