BUG: Unhandled Exception Filter Not Called Inside Debugger
ID: Q173652
|
The information in this article applies to:
-
Microsoft Win32 Application Programming Interface (API), used with:
-
Microsoft Windows NT versions 3.5, 3.51, 4.0
-
Microsoft Windows 95
-
Microsoft Windows 98
SYMPTOMS
Win32 processes can install an unhandled exception filter function to catch
exceptions that are not handled in a __try/__except block on a process-wide
basis. When debugging such a process, you find that the unhandled exception
filter is never executed, even when you put a breakpoint inside it.
However, when the process is not being debugged, its unhandled exception
filter is called as expected.
CAUSE
When called from a process being debugged, the UnhandledExceptionFilter()
Win32 API function does not call the application-installed unhandled
exception filter.
RESOLUTION
UnhandledExceptionFilter should call the application-installed unhandled
exception filter for processes that are being debugged in addition to those
not being debugged.
One way to debug an unhandled exception filter function is to put a
__try/__except block around all of the code inside the main() or WinMain()
function as follows:
void main (int argc, char **argv)
{
__try
{
// all of code normally inside of main or WinMain here...
}
__except (MyUnFilter (GetExceptionInformation()))
{
OutputDebugString ("executed filter function\n");
}
}
This work around behaves slightly differently from an unhandled exception
filter in that it will only be called for the thread executing the main()
or WinMain() function. If you are debugging a multithreaded application,
then you will need to add a similar __try/__except block inside of each
thread function.
If you don't want to add new __try/__except blocks to debug an unhandled
exception filter, you should use other methods such as assert, trace
outputs, and debugging code to validate the behavior of the exception
handler.
STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article. We are researching this bug and will post
new information here in the Microsoft Knowledge Base as it becomes
available.
MORE INFORMATION
The purpose of an unhandled exception filter function is to give a process
the opportunity to respond to exceptions that occur outside any
__try/__except block. Unhandled exception filters are process-wide; if any
thread causes an exception, but does not handle it, the unhandled exception
filter will get called. Once called, the filter function can fix the cause
of the exception and continue execution, or it can pass the error to the
default unhandled exception handler, which terminates the process.
Win32 applications can install a process-wide unhandled exception filter
with the SetUnhandledExceptionFilter() API function. The Microsoft Visual
C++ C Runtime (CRT) library startup code implements a __try/__except block
around the main() function. When an exception is caught by this block, its
exception filter function, named _XcptFilter, is called. _XcptFilter does
two things: it maps the Win32 exceptions to signals used by the signal()
CRT function, and dispatches signals to their appropriate handlers. If a
signal's handler is set to SIG_DFL (as is the case by default), _XcptFilter
calls the UnhandledExceptionFilter() API.
The UnhandledExceptionFilter() API determines whether the process is being
debugged. If it is, then UnhandledExceptionFilter passes the exception
first to the debugger, and then is supposed to call the process's unhandled
exception filter.
If the process isn't being debugged, then UnhandledExceptionFilter calls
the process's unhandled exception filter. Depending on the filter
function's return, UnhandledExceptionFilter either continues execution at
the point of the exception, or displays a system-modal dialog box informing
the user that the application is to be terminated due to an unhandled
exception.
Steps to Reproduce Behavior
Compile the following sample code, and then set a breakpoint inside
MyUnFilter. Observe that the breakpoint never gets hit.
/*
Demonstrates how to use SEH so that unhandled exception filter
can trap unhandled instructions.
*/
#include <windows.h>
#include <stdio.h>
LONG WINAPI MyUnFilter (struct _EXCEPTION_POINTERS *lpExceptionInfo);
void main (void)
{
LPBYTE lpBuff = NULL;
SetUnhandledExceptionFilter (MyUnFilter);
*lpBuff = 54;
}
LONG WINAPI MyUnFilter (struct _EXCEPTION_POINTERS *lpExceptionInfo)
{
static int s_SigCount = 0;
DWORD dwExceptCode = lpExceptionInfo -> ExceptionRecord ->
ExceptionCode;
LONG lResult;
if (dwExceptCode == EXCEPTION_ACCESS_VIOLATION)
{
printf ("access violation caught by MyUnFilter\n");
++s_SigCount;
// test case to keep this from going on forever (since we're not
// fixing the AV)
if (s_SigCount < 5)
lResult = EXCEPTION_CONTINUE_EXECUTION;
else
lResult = EXCEPTION_EXECUTE_HANDLER;
}
else
lResult = EXCEPTION_CONTINUE_SEARCH;
return lResult;
}
Additional query words:
Keywords : kbKernBase kbExceptHandSEH kbDSupport kbGrpKernBase
Version : winnt:3.5,3.51,4.0
Platform : winnt
Issue type : kbbug