Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement top level exception handling?

I recently had to develop an additional module for an existing service developed by a colleague. He had placed a try/catch block in the main working function for catching all unhadled exceptions that bubbled up to this level, logging them together with stack trace info etc:

try
{
    // do main work
}
catch(Exception ex)
{
    // log exception info
}

While this makes the program very stable (as in 'unlikely to crash'), I hate it because when I am testing my code, I do not see the exceptions caused by it. Of course I can look at the exception log and see if there are new entries, but I very much prefer the direct feedback of getting the exception the moment it is thrown (with the cursor on the right line in the code, please).

I removed this top level try/catch at least while i was still coding and testing. But now my task is finished and I have to decide wether to put it back in for the release, or not. I think that I should do it, because it makes the service more stable, and the whole point of it is that it runs in the background without needing any supervision. On the other hand I have read that one should only call specific exceptions (as in IoException), not generically Exception.

What is your advice on this issue?

By the way, the project is written in C#, but I am also interested in answers for non .NET languages.

like image 218
Treb Avatar asked Mar 05 '09 21:03

Treb


3 Answers

Put it back.

The exception should be only relevant while testing. Otherwise it doesn't make sense pop it to the user.

Logging is fine.

You may additionally use the DEBUG symbol defined by Visual Studio for debug builds as a flag.

    ...
    } catch( Exception e ) { 
#if DEBUG
          throw;
#else
          log as usual 
#endif
    }

So next time a modification is needed the debug flag should be set to true and the exception will pop up.

like image 182
OscarRyz Avatar answered Oct 26 '22 15:10

OscarRyz


In any Java application, you just about always want to define an exception handler for uncaught exceptions with something like this:

Thread.setDefaultUncaughtExceptionHandler( ... );

where the object that will catch these uncaught exceptions will at least log the failure so you have a chance to know about it. Otherwise, there is no guarantee that you'll even be notified that a Thread took an Exception -- not unless it's your main Thread.

In addition to doing this, most of my threads have a try/catch where I'll catch RunnableException (but not Error) and log it ... some Threads will die when this happens, others will log and ignore, others will display a complaint to the user and let the user decide, depending on the needs of the Application. This try/catch is at the very root of the Thread, in the Runnable.run() method or equivalent. Since the try/catch is at the root of the Thread, there's no need to sometimes disable this catch.

When I write in C#, I code similarly. But this all depends on the need of the application. Is the Exception one that will corrupt data? Well then, don't catch and ignore it. ALWAYS log it, but then Let the application die. Most Exceptions are not of this sort, however.

like image 22
Eddie Avatar answered Oct 26 '22 17:10

Eddie


Ideally you want to handle an exception as close to where it occured as possible but that doesn't mean a global exception handler is a bad idea. Especially for a service which must remain running at all costs. I would continue what you have been doing. Disable it while debugging but leave it in place for production.

Keep in mind it should be used as a safety net. Still try to catch all exceptions before they elevate that far.

like image 30
Kenneth Cochran Avatar answered Oct 26 '22 15:10

Kenneth Cochran