Re: Function names for managed callstack under SOS debugging of .NET 2.0 app
- From: "Daniel Bowen" <DanielBowenWl@xxxxxxxxxxxxxxxxx>
- Date: Wed, 12 Jul 2006 16:55:32 -0600
Thanks for your response!
Short answer: try running a .NET 2.0 application that uses
SetUnhandledExceptionFilter in native code to write mini-dump files with
MiniDumpNormal _on a different machine than it was compiled on_, then induce
an unhandled exception on a worker thread, and I think you'll see the
problem I'm seeing.
Long answer:
Based on my understanding, your application use
SetUnhandledExceptionFilter
API to setup the default unhandled exception handler for all the unhandled
exceptions in the process, you handler writes a minidump for the
exception,
also it uses SOS.dll !PE command to get the managed call stack and
exception information for managed .Net thread. The problem is the method
symbol name for your application is not display correctly in the !PE
command.
That's pretty much correct. The EXE is a .NET 2.0 WinForm application. We
use some managed assemblies (DLLs), and several native DLLs (C++). We have
a DLL in C/C++ that is dedicated to doing the SetUnhandledExceptionFilter
and generating the mini-dump. We call an "Install" function in this DLL
through interop / P/Invoke that the .NET WinForm application calls in
"Main". We call an "Uninstall" function right before the application exits
Main. On the main GUI thread in the .NET application, we use
Application.ThreadException (which only catches managed exceptions on the
calling managed thread). For all other unhandled exceptions, whether its on
a native thread (_beginthreadex) or a managed thread (Thread.Start), we
depend on our unhandled exception handler to catch the exception and
generate a mini-dump. We want both native and managed exceptions in
mini-dumps. If a customer runs into an unhandled exception, we have
diagnostics support that sends us the mini-dump, so we'd like to have files
that aren't too large to e-mail.
We redistribute dbghelp.dll version 6.6.0.5, and use that for the
MiniDumpWriteDump call. SOS is used in post-mortum debugging using either
WinDbg or Visual Studio 2005.
First, I want to notify you that SetUnhandledExceptionFilter is a
per-thread setting for unhandled exception, so you have to call it every
time for all the threads in your application. I assume you have awared of
this point.
That's true for the managed "Application.ThreadException", but not for the
unmanaged "SetUnhandledExceptionFilter". There's also
AppDomain.CurrentDomain.UnhandledException that can be thrown into the mix,
but if you use that, the unhandled exception still propogates on. Plus, we
want to catch native unhandled exceptions. So we use
Application.ThreadException to catch exceptions on the main GUI thread in
..NET (otherwise there's a handler from .NET that catches it and displays its
own dialog), and our exception handler put in by SetUnhandledExceptionFilter
to catch unhandled exceptions by all other threads (managed or native).
I am not sure what role does "ngen" play in your application. Do you
always
run your application after ngen? For troubleshooting's sake, is it
possible
for us to use the managed assembly for debugging purpose? This will
eliminate the complexity introduced by ngen.
We can leave ngen out of the discussion for now - at least for our own code.
Since I do not have the details information regarding how you use
MiniDumpWriteDump to write out the minidump, I tried to use windbg to
simulate the process
...
It seems my method symbol is displayed correctly without your problem. I
assume this main that the dump windbg generated is different somewhat
different from yours. So the problem may lie in the code you generate the
dump.
I recommend you give these steps a test and confirm my statement. If there
is anything I have misunderstood, please feel free to tell me, thanks!
OK, I've written a small application that uses a very simplified version of
things. It consists of a .NET WinForm application and a native DLL that
does SetUnhandledExceptionFilter. You can download it from here:
http://tinyurl.com/oa869
In that application, I don't use Application.ThreadException on the main
thread. I only install the unhandled exception filter. The mini-dump
currently is set to use MiniDumpNormal in the MiniDumpWriteDump call.
Here's what I've found from running it:
1. If you compile debug or release, run outside the debugger, on the same
machine or different machine, and choose the "crash on GUI thread", you get
a dialog from .NET with details on the exception.
2. If you compile debug or release, run outside the debugger on the same
machine, and choose the "crash on worker thread", the unhandled exception
filter kicks in, and generates a mini-dump for you (it puts it in the EXE's
directory). Opening this mini-dump in WinDbg and doing
.ecxr
.load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos
!pe
(or !clrstack, etc.)
shows a fine looking call stack, with the name of the functions in the
WinForm. For example:
0:004> !pe
Exception object: 0128e014
Exception type: System.DivideByZeroException
Message: Attempted to divide by zero.
InnerException: <none>
StackTrace (generated):
SP IP Function
0340F8AC 00D00672
MiniDumpWithClrInfoTest.MainForm.CrashTypeOption_DivideByZero()
0340F8B4 793D7A7B
System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
0340F8BC 793683DD
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object)
0340F8D4 793D7B5C System.Threading.ThreadHelper.ThreadStart()
StackTraceString: <none>
HResult: 80020012
the dump file for this one was 90 KB.
3. Now, take the EXE (MiniDumpWithClrInfoTest.exe), the DLL
(CrashHandlerTest.dll), dbghelp.dll (the 6.6 version in the Debug or Release
directory), and copy them to a different machine with .NET 2.0 installed.
If you run and choose "crash on worker thread", the unhandled exception
filter kicks in, and generates a mini-dump for you (it puts it in the EXE's
directory). Now take this .dmp file back to the machine you compiled on.
Opening this mini-dump in WinDbg and doing
.ecxr
.load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos
!pe
(or !clrstack, etc.)
shows a stack with "Unknown" for the function name:
0:004> !pe
Exception object: 01293834
Exception type: System.DivideByZeroException
Message: Attempted to divide by zero.
InnerException: <none>
StackTrace (generated):
SP IP Function
0336F8AC 00C90672 MiniDumpWithClrInfoTest.exe!Unknown
0336F8B4 793D7A7B
System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
0336F8BC 793683DD
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,
System.Threading.ContextCallback, System.Object)
0336F8D4 793D7B5C System.Threading.ThreadHelper.ThreadStart()
StackTraceString: <none>
HResult: 80020012
the dump file for this one was 87 KB.
4. If I change the MiniDumpNormal option in the MiniDumpWriteDump call to
MiniDumpWithCodeSegs, it seems that if I get an exception while running on a
different machine, that I DO get the .NET functions names when doing !pe.
However, the dump file goes from 87KB to nearly 40 MB. In our real
application, the smaller dumps are typically around 300KB, and using
MiniDumpWithCodeSegs creates around 70 MB dumps.
In the zip file, I've included the debug and release versions of the
application and DLL compiled so that you can test the "compiled on another
machine" aspect of the problem. You can move those somewhere else, so they
don't get lost in the next recompile you do.
If you look at the call stack from a native point of view, you can see that
"mscorlib.ni.dll" is on the stack. My guess is that when .NET 2.0 installs,
it ngen's the framework assemblies. When the mini-dump is captured on the
same machine that it is built, then we get all the CLR meta-data that we
need for a nice callstack, even with MiniDumpNormal. But when a mini-dump
is captured when running on a different machine, something goes wrong for
MiniDumpNormal.
The new dbghelp.dll is a must of course for even a shot at getting good CLR
info (the one with XP doesn't cut it).
My question is - what can we change with how we capture the mini-dump to
capture enough information for function names in the callstack on managed
threads when using SOS to analyze the dump file generated from a customer's
machine, but still keep the dump file relatively small (under a couple MB
preferrably, several hundred KB ideally)?
Thanks!
-Daniel
.
- Follow-Ups:
- Re: Function names for managed callstack under SOS debugging of .NET 2.0 app
- From: "Jeffrey Tan[MSFT]"
- Re: Function names for managed callstack under SOS debugging of .NET 2.0 app
- References:
- Function names for managed callstack under SOS debugging of .NET 2.0 app
- From: Daniel Bowen
- RE: Function names for managed callstack under SOS debugging of .NET 2.0 app
- From: "Jeffrey Tan[MSFT]"
- Function names for managed callstack under SOS debugging of .NET 2.0 app
- Prev by Date: Re: Function names for managed callstack under SOS debugging of .NET 2.0 app
- Next by Date: sql server 2005 tools configuration starts when I build a distribution project (VB 2005)
- Previous by thread: Re: Function names for managed callstack under SOS debugging of .NET 2.0 app
- Next by thread: Re: Function names for managed callstack under SOS debugging of .NET 2.0 app
- Index(es):
Relevant Pages
|
Loading