When faced with this problem, I grabbed Jochen Klambach's StackWalker from CodeProject. Update: StackWalker has now graduated to Codeplex. Definitely get the codeplex release; it includes several updates and fixes.
It will print the stack for your code when the filter crashes.
The way I did it was this: within OnAuthComplete in my filter, which is where my filter does all the work, I surrounded the logic with a try...except:
__try
{
dwRetval = DoRewrites(...);
}
__except ( ExcFilter(GetExceptionInformation()) )
{
}
And then, ExcFilter is defined this way:
extern "C" int ExcFilter(EXCEPTION_POINTERS *pExp)
{
MyLoggingStackWalker *sw = new MyLoggingStackWalker();
sw->ShowCallstack(GetCurrentThread(), pExp->ContextRecord);
return EXCEPTION_CONTINUE_SEARCH; // allow the process to crash
}
The LoggingStackWalker derives from StackWalker, and overrides the OnOutput method to send that output to a log file. It also sets the search path for PDB files to include the directory where the DLL is found.
class MyLoggingStackWalker : public StackWalker
{
public:
MyLoggingStackWalker() : StackWalker()
{
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
// add the directory for the ISAPI DLL, to the search path for PDB files
this->m_szSymPath = (LPSTR) malloc(_MAX_PATH);
_splitpath_s(DllLocation, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
_makepath_s(this->m_szSymPath, _MAX_PATH, drive, dir, NULL, NULL);
}
virtual void OnOutput(LPCSTR szText)
{
LogMessage((char*)szText);
StackWalker::OnOutput(szText);
}
};
To demonstrate it, I pass a bad pointer into vscprintf in the code. This is what the resulting stack trace looks like on IIS7. You can see the first couple frames are in the C runtime, with line numbers, too. (The StackWalker actually downloads symbol files from the MS symbol server, if you use the default settings. You can turn this off if you like.)
Then the next bunch of frames are from my code. It pinpoints the location of the problem. The stack frames following mine - Those are all the IIS modules. This is IIS7 on Vista; I guess the symbol server didn't have symbols for those modules. Anyway as you can see the stacktrace leaves no doubt as to where the problem is.
f:\dd\vctools\crt_bld\self_x86\crt\src\output.c (1068): _output_l
f:\dd\vctools\crt_bld\self_x86\crt\src\vsprintf.c (405): _vscprintf_helper
f:\dd\vctools\crt_bld\self_x86\crt\src\vsprintf.c (414): _vscprintf
c:\dev\isapi\filter\logger.c (193): LogMessage
c:\dev\isapi\filter\rewriter.c (2036): EvaluateRewrites
c:\dev\isapi\filter\rewriter.c (789): DoRewrites
c:\dev\isapi\filter\rewriter.c (955): OnAuthComplete
c:\dev\isapi\filter\rewriter.c (1139): HttpFilterProc
60531896 module(filter): (filename not available): (function-name not available)
60531FAB module(filter): (filename not available): (function-name not available)
605314E3 module(filter): (filename not available): (function-name not available)
60531276 module(filter): (filename not available): (function-name not available)
6D122EA0 module(iiscore): (filename not available): (function-name not available)
6D123696 module(iiscore): (filename not available): (function-name not available)
6D12AA4C module(iiscore): (filename not available): (function-name not available)
6D125D3B module(iiscore): (filename not available): (function-name not available)
6D1220F4 module(iiscore): (filename not available): (function-name not available)
6D124EEF module(iiscore): (filename not available): (function-name not available)
6D12C6B8 module(iiscore): (filename not available): (function-name not available)
70CB13B3 module(w3dt): (filename not available): UlAtqGetContextProperty
70CB11DA module(w3dt): (filename not available): (function-name not available)
71A42611 module(W3TP): (filename not available): THREAD_POOL::PostCompletion
71A42812 module(W3TP): (filename not available): OverrideThreadPoolConfigWithRegistry
71A41E85 module(W3TP): (filename not available): (function-name not available)
76A54911 module(kernel32): (filename not available): BaseThreadInitThunk
7727E4B6 module(ntdll): (filename not available): __RtlUserThreadStart
7727E489 module(ntdll): (filename not available): _RtlUserThreadStart
7727E489 module(ntdll): (filename not available): _RtlUserThreadStart