6

In all WPF application I develop there is a global exception handler subscribed to AppDomain.CurrentDomain.UnhandledException which logs everything it can find and then shows a dialog box telling the user to contact the author, where the log file is etc. This works extremely well and both clients and me are very happy with it because it allows fixing problems fast.

However during development of a mixed WPF / C# / CLI / C++ application there are sometimes application crashes that do not make it to the aforementioned exception handler. Instead, a standard windows dialog box saying "XXX hast stopped working" pops up. In the details it shows eg

 Problem Event Name: BEX
 Application Name:   XXX.exe
 Fault Module Name:  clr.dll
 ...

This mostly happens when calling back a managed function from within umanaged code, and when that function updates the screen. I didn't took me long to figure out the root cause of problem, but only because I can reproduce the crash at my machine and hook up the debugger: in all occasions the native thread was still at the point of calling the function pointer to the managed delegate that calls directly into C#/WPF code.

The real problem would be when this happens on a client machine: given that usually clients are not the best error reporters out there it migh take very, very long to figure out what is wrong when all they can provide me are the details above.

The question: what can I do to get more information for crashes like these? Is there a way to get an exception like this call a custom error handler anyway? Or get a process dump? When loading the symbols for msvcr100_clr0004.dll and clr.dll (loaded on the thread where the break occurrs), the call stack is like this:

msvcr100_clr0400.dll!__crt_debugger_hook()  
clr.dll!___report_gsfailure()  + 0xeb bytes 
clr.dll!_DoJITFailFast@0()  + 0x8 bytes 
clr.dll!CrawlFrame::CheckGSCookies()  + 0x2c3b72 bytes  

Can I somehow hook some native C++ code into __crt_debugger_hook() (eg for writing a minidump)? Which leads me to an additional question: how does CheckGSCookies behave on a machine with no debugger installed, would it still call the same code?

update some clarification on the code: native C++ calls a CLI delegate (to which a native function pointer is acquired using GetFunctionPointerForDelegate which in turn calls a C# System.Action. This Action updates a string (bound to a WPF label) and raises a propertychanged event. This somehow invokes a buffer overflow (when updating very fast) in an unnamed thread that was not created directly in my code.

update looking into SetUnhandledExceptionFilter, which didn't do anything at first, I found this nifty article explaining how to catch any exception. It works, and I was able to write a minidump in an exception filter installed by using that procedure. The dump gives basically the same information as hooking the debugger: the real problem seems to be that the Status string is being overwritten (by being called from the native thread) while at the same time being read from the ui thread. All nice ans such, but it does require dll hooking which is not my favorite method to solve things. Another way would still be nice.

6
  • Correct me if I'm wrong: 1. Target platform is Windows. 2 You are installing an application-wide Unhandled Exception Filter. 3. You create some threads and load some DLL's dynamically. 4. You call some DLL functions and these functions throw exceptions that do not make it to your Handler. Is that correct? Also, these exceptions happen in one of your threads or in the (possibly) threads created by DDLs' functions? Commented Jan 10, 2012 at 12:35
  • @AzzA 1. yes 2. yes, but using CurrentDomain.UnhandledException, not sure if this is enough 3. yes 4. see update Commented Jan 10, 2012 at 13:33
  • Things to try: 1. Try using SetUnhandledExceptionFilter WinAPI instead of CurrentDomain.UnhandledException (although, I seriosuly suspect it's a wrapper around aforementioned WinAPI). 2. It looks like the DLLs you load dynamically might be resetting Handler to the default NULL in their start-up. The point I'm trying to make is that you have to install your filter after the DLLs are loaded, taking into account that they might be delay-loaded - are you loading them using linker or LoadLibrary inside your code? Commented Jan 10, 2012 at 13:50
  • To add: SetUnhandledExceptionFilter installs filter for all current and future threads of the process, so even DLLs create some threads, that should not be a problem. Also, I assume, exceptions occur after you install the filer. Otherwise, it's pretty straightforward. Commented Jan 10, 2012 at 14:05
  • @Azza the dlls are not resetting the CurrentDomain.UnhandledException: after loading everything, normal C# exceptions are still catched. The dlls are loaded as follows: the main C# app loads other assemblies using Load/LoadFrom. These assemblies in turn load a C++/CLI dll (not sure how this is done), which in turn is linked to a bunch of C++ dlls. I'll see what SetUnhandledExceptionFilter can do though, sounds interesting. Commented Jan 10, 2012 at 14:30

1 Answer 1

5

The .NET 4 version of the CLR has protection against buffer overflow attacks. The basic scheme is that the code writes a "cookie" at the end of an array or stack frame, then checks later if that cookie still has the original value. If it has changed, the runtime assumes that malware has compromised the program state and immediately aborts the program. This kind of abort does not go through the usual unhandled exception mechanism, that would be too exploitable.

The odds that your program is really being attacked are small of course. Much more likely is that your native code has a pointer bug and scribbles junk into a CLR structure or stack frame. Debugging that isn't easy, the damage is usually done well before the crash. One approach is to comment out code until the crash disappears.

Sign up to request clarification or add additional context in comments.

2 Comments

This is quite interesting. I saw these things installed once by MS compiler when, exactly, I was answering Buffer Overflow problem. It has disassembly and shows security_cookie installed. It seems it's not only .NET, but MS compilers in general. Thanks for bringing it to my attention!
the abort does seem to go through the usual mechanism, but with some quirks; see update

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.