The SetUnhandledExceptionFilter API Function


The SetUnhandledExceptionFilter API Function

Interestingly, crashes have a habit of never happening where you expect them. Unfortunately, when your users experience crashes in your program, they just see the Application Error dialog box, and then maybe Dr. Watson gives them a little information to send to you to figure out the problem. As I mentioned earlier in this chapter, you can devise your own dialog boxes and handlers to get the information you really need to solve the crash. I've always referred to these exception handlers along with their corresponding exception filters as crash handlers.

In my experience, crash handlers have excellent debugging capabilities. I've worked on numerous projects where we'd gain control right as the application died, gather all the information about the crash (including the state of the user's system) into a file, and if the project was a client application, pop up a dialog box with a technical support number. In some cases, we architected the application so that we could iterate through the program's main objects, enabling us to report down to the class level which objects were active and what they contained. We were logging almost too much information about the program's state. With a crash report, we had a 90 percent chance of duplicating the user's problem. If that isn't proactive debugging, I don't know what is!

You create crash handlers through the magic of the SetUnhandledExceptionFilter API function. Amazingly, this functionality has been in Win32 since Microsoft Windows NT 3.5, but it's almost never mentioned in the documentation. At the time I wrote this chapter, in MSDN Online, this function was mentioned only eight times.

Needless to say, I find SetUnhandledExceptionFilter powerful. Just by looking at the function name—SetUnhandledExceptionFilter—you can probably guess what the function does. SetUnhandledExceptionFilter allows you to specify an unhandled exception filter function that should be called when an unhandled exception occurs in a process. The one parameter to SetUnhandledExceptionFilter is a pointer to an exception filter function that is called in the final __except block for the application. This exception filter returns the same value that any exception filter would return: EXCEPTION_EXECUTE_HANDLER, EXCEPTION_CONTINUE_EXECUTION, or EXCEPTION_CONTINUE_SEARCH. You can do any exception handling you want in the exception filter, but you need to be careful about blown stacks in your exception filter. To be on the safe side, you might want to avoid any C run-time library calls as well as MFC. Although I'm obligated to warn you about these possibilities, I can assure you that the vast majority of your crashes will be access violations—you shouldn't have any problems if you write a complete crash handling system in your exception filter and exception handler, provided you check the exception reason first and avoid function calls when the stack is blown.

Your exception filter also gets a pointer to an EXCEPTION_POINTERS structure. In Listing 13-4, I'll present several routines that translate this structure for you. Because each company has different crash handler needs, I'll let you write your own.

You need to keep in mind a couple of issues when you're using SetUnhandledExceptionFilter. The first is that you can't use standard user-mode debuggers to debug any unhandled exception filter you set. This restriction actually makes sense, because the operating system needs to take over the final exception filter when running under a debugger so that the operating system can properly report the final crash to the debugger. However, it can make debugging your final crash handler a bit of a pain. One workaround you can use to debug your unhandled exception filter is to call it from a regular SEH exception filter. You can find an example of this workaround in the Baz function in BugslayerUtil\Tests\CrashHandler\CrashHandler.CPP, which is part of this book's source code.

Another issue is that the exception filter you specify by calling SetUnhandledExceptionFilter is global to your process. If you build the coolest crash handler in the world for your ActiveX control and the container crashes—even if it's not your fault—your crash handler will be executed. Don't let this possibility keep you from using SetUnhandledExceptionFilter, though. I have some code that might help you out.

start sidebar
Common Debugging Question: Is there anything you can do to fix blown stacks from infinite recursion?

Infinite recursion is not, thank goodness, that common, but when it does happen, it's nearly impossible to debug. If you've ever seen an application appear to pause for a second or so and completely disappear without displaying an Application Error dialog box, you're almost certainly looking at infinite recursion. If you can't even get a chance to debug the application, it's very hard to figure out what went wrong with it.

Fortunately, the new _resetstkoflw C run-time function attempts to get you some stack space so that you can at least report the error. If you'd like to see how _resetstkoflw does its magic, check out its implementation, which is included in RESETSTK.C.

end sidebar




Debugging Applications for Microsoft. NET and Microsoft Windows
Debugging Applications for MicrosoftВ® .NET and Microsoft WindowsВ® (Pro-Developer)
ISBN: 0735615365
EAN: 2147483647
Year: 2003
Pages: 177
Authors: John Robbins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net