Our legacy C++ app crashing at LeaveCriticalSection.
The application is a single threaded and am not sure for what reasons critical section is used since it is a legacy code.
Still trying to find out the reasons of crash.
The crash window just says unhandled exception.
The app only crashes in release mode
Related
I use Google Breakpad for crash reporting a C++ app on Mac and Windows. On both platforms, Breakpad works by registering a handler for uncaught exceptions. That handler is triggered by most anything that would normally crash a process, e.g. dereferencing a null pointer.
But now I have a scenario where the handler isn't being invoked and the process crashes to the OS crash reporter. It's 100% reproducible, but I can't debug it because attaching a debugger to the process preempts the uncaught exception handler.
What techniques (other than copious printfs) can help me trace where the code flow is going if not to my handler? I think I'd like some IDE setting to let my debugger (Visual Studio and/or Xcode) step past the null pointer dereference and into the C++ runtime's handler code. But other techniques would be welcome too.
I have a minimal reproduction of my problem scenario here: https://bugreports.qt.io/browse/QTBUG-50061
I have a plugin for an old application written in C++ 6.0. The files are connected in the following fashion:
Starts with: C++ 6.0 .exe (third party application)
loads: C++ 6.0 simple loader .dll (officially a plugin for application)
loads: C++ 10.0 simple loader .dll (managed C++/CLI)
loads one of: C# .NET 4.0 assembly which contains plugin
loads: C++ 6.0 .dll which provides API for C# plugin to talk to application
The problem is once .NET 4.0 is loaded into the C++ 6.0 application, the next time it throws a native exception, .NET uses a vectored exception handle to handle the exception and fails spectacularly. The part that makes it really bad is that the vectored exception handler throws an exception itself, which it then tries to handle, and that fails, and it gets stuck in an infinite loop until it gets a stack overflow exception.
Here's what the stack trace looks like:
// The next 7 lines repeat until the stack overflows
clr.dll!CreateHistoryReader()
clr.dll!CreateHistoryReader()
clr.dll!GetMetaDataInternalInterfaceFromPublic()
ntdll.dll!_RtlpCallVectoredHandlers#12()
ntdll.dll!_RtlCallVectoredExceptionHanders#8()
ntdll.dll!_RtlDispatchException#8()
ntdll.dll!_KiUserExceptionDispatcher#8()
// Below is an example exception that causes this:
KernelBase.dll!RaiseException()
rpcrt4.dll!RpcRaiseException()
rpcrt4.dll!I_RpcTransConnectionFreePacket()
rpcrt4.dll!I_RpcBindingInqCurrentModifiedId()
rpcrt4.dll!NdrConformantStringMemorySize()
rpcrt4.dll!NdrComplexStructMarshall()
rpcrt4.dll!SimpleTypeMemorySize()
rpcrt4.dll!NdrClientCall2()
ole32.dll!ServerRegisterClsid(void* hRpc, void* phProcess, _RegInput* pregin, _RegOutput** ppregout unligned long* prpcstat
ole32.dll!CRpcResolver::NotifyStarted(_RegInput* pRegIn, _RegOutput** ppRegOut)
ole32.dll!CClassCache::ResumeProcessClassObjects()
There are only really 2 ways to deal with this and neither are very great:
I found with a trivial program, if I completely isolate .NET on its own thread, the non-.NET threads never run into this issue. This doesn't work in practice because the plugin API needs to make synchronous callbacks to the .NET plugin.
The other I've come up with is to iterate over every single address in memory until a call to "RemoveVectoredExceptionHandler(HANDLE)" succeeds and removes .NET's vectored exception handler. (I can speed up the search by registering my own VEH temporarily and use its handle as a starting spot). This tends to break debugging of native code.
Is there any better way to deal with this?
The CLR seems to have changed behaviors since I reported this issue. Since the CLR is now open source, it's possible to see what's going on under the hood.
The CLR installs its own vectored exception handler. During vectored exception handling, it does a stack check to make sure there's enough space, unless it's a stack overflow exception. The stack space check goes wrong, and it thinks it's out of space when it's not, so it throws a stack overflow exception to unroll the stack enough to do actual work.
I was able to trick .NET into not crashing the app by installing 2 vectored exception handlers, one before and one after. If it's the exception type that's causing the crash, I change the exception code to STACKOVERFLOW in the first handler, and change it back in the second handler. This way the CLR thinks it's a stack overflow exception and doesn't try to do stack probing.
I'm writing small utility (VC 2010, no clr) that does one simple task (rasterizing) using 3rd party library. Later utility will be used by bigger application. Sometimes the utility crashes because of some heap corruption in 3rd party library. That is OK, but Windows (Vista/2008) shows well known dialog "Program has stopped working ... Close/Debug program." which is not appropriate in my case (Server side). Utility should crash/terminated silently w/o any visible effects.
To do that I installed SEH for unhandled exception (SetUnhandledExceptionFilter). The handler is perfectly invoked for exceptions like AV ( *(PDWORD)0 = 0 ), but for some reason it is not invoked in the case of heap corruption. Corruption happens in dllmain of one of 3rd party library dlls while it is being unloaded.
Couple of questions. Can anybody explain why the handler is not invoked? Is there any another way to prevent that dialog?
Apparently it's intentional that heap corruptions cannot be caught by user-defined exception handlers, even though they're emitted as exceptions with their own exception code (0xC0000374 "STATUS_HEAP_CORRUPTION"). Here's a Visual C++ bug report which was basically closed as "won't fix":
https://connect.microsoft.com/VisualStudio/feedback/details/664497/cant-catch-0xc0000374-exception-status-heap-corruption
As you have discovered, this is not a bug in the compiler or the OS. The heap corruption that your function causes is treated as a critical error, and as part of handling that error the OS terminates the process. This is what causes your exception handlers to not be invoked.
I'd guess that Windows Error Reporting or other ways of creating a crash dump could still catch it.
As for preventing the dialog, in the registry you can either disable WER completely or just disable the dialog so that the process won't block:
https://msdn.microsoft.com/de-de/library/windows/desktop/aa366711(v=vs.85).aspx (see "DontShowUI")
but for some reason it is not invoked in the case of heap corruption. Corruption happens in dllmain of one of 3rd party library dlls while it is being unloaded.
Heap corruption is undefined behavior. It may throw exceptions, it may do otherwise. If a buggy third party library is messing up your heap, then the question is "why are you allowing them to mess with your heap in the first place?"
The "program has stopped working" dialog is shown whenever a process terminates abnormally. Not all abnormal process terminations result from exceptions. Many errors (such as stack overflow, misaligned stack, etc.) cause instant termination of the process, which may show that message but will not give you a chance to handle the error.
(Also, see Hans' awesome comment above)
I have a DLL that's being injected into very old, buggy and now unsupported by it's developer application. Sometimes that application crashes, and I need some way to catch literally all unhandled exceptions (from DLL) that may occur to save data and only then allow the app to crash. How can I achieve that?
For now, there is an external debugger for that purpose, but it's just too slow and also buggy to keep it that way.
You have to start a new process which hosts the DLL. If the DLL is going to crash, it's going to bring down the process, whether you like it or not. Sure, you could attempt to catch an exception or something like that, but if the exception is being thrown, that means memory is corrupted. It is better to crash catastrophically than to have the program continuing to run in an inconsistent state.
The windows shell is a program which actually does this -- it launches some plugins in a surrogate process, so that if the plugin crashes, it doesn't bring down the whole shell. You'd need to use interprocess communication to communicate between yourself and the surrogate you start.
In MSVC, how can I make any unhandled C++ exception (std::runtime_error, for instance) crash my release-compiled program so that it generates a dump with the full stack from the exception throw location?
I have installed NTSD in the AeDebug registry and can generate good dumps for things like memory access violation, so the matter here comes down to crashing the program correctly, I suppose.
Thanks in advance.
I finally cracked it down.
Use the set_terminate() function to register a handler for every thread
In you main function(), make it impossible for external DLLs (event Windows') to successfully call SetUnhandledExceptionFilter(). A great article on how to do that here: http://www.debuginfo.com/articles/debugfilters.html#overwrite .
As for the handle itself, it is quite straightforward:
void Terminate()
{
OutputDebugStringA("Terminate\r\n");
RaiseException(0xE0000010, EXCEPTION_NONCONTINUABLE, 0, 0);
}
Calling RaiseException() like the above example is enough to make the process crash and produce my mush desired dump.
Just so you know, the problem I was having was:
The IPHelper Windows API loads dynamically another Windows DLL
This DLL uses Windows own version of the C runtime (MSVCRT instead of MSVCRT90)
The new C++ runtime calls SetUnhandledExceptionFilter() on startup to catch C++ exceptions. Since the latest filter for C++ exceptions is the one who gets to call the handle set by set_terminate(), my handle wasn't called.
SetUnhandledExceptionFilter and DebugBreak should probably do the job.
Edit: oops, rereading, you want to deal with uncaught C++ exceptions. That would be a bit trickier to do well -- by the time you (normally) get wind of a C++ exception, it's already unwound the stack back to the level of the handler. You don't have any real way to know an exception has been thrown until a catch is invoked, but by then the stack has been unwound.
Look into using the Windows Debugger.
Windbg – wraps KD and NTSD with a decent UI.
Also check out ADPlus that comes with the Windows Debugger.
Here is a good place to start learning how to use it.