Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting if an exception is a Corrupted State Exception

I have some code that is calling Rotativa, which calls wkhtml2pdf. I suspect from the behavior that I'm seeing that wkhtml2pdf.exe is causing a Corrupted State Exception (CSE) to be thrown. I want to catch and log a CSE if thrown, so I can track down where it is happening.

When I leave the app running overnight in the debugger, when I come back VS has shutdown. Sometimes it has restarted, sometimes not. Suspecting Memory Corruption I started researching and stumbled on the CSE handling.

I'm doing something like this:

[HandleProcessCorruptedStateExceptions]
void DoStuff()
{
     try
     {
          DOThatThingThatMakesTheDebuggerHaltAndShutDown();
     }
     catch(Exception ex)
     {
            //how do I detect that it's a CSE in here, so I can log it especially blatantly
     }
}

Is there a way to detect if the exception is a CSE in the General Catch?

I saw a kludge where they have 2 general exception clauses. The inner one does not handle CSEs and sets a flag. If the outer one gets called without the flag then it is a CSE, but I'm hoping for something cleaner. I want to do is log this bad state, then pass it along to the application to bubble up normally.

When I look at the error in the event log that brought down VS2013 I get this:

Application: devenv.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: exception code c0000005, exception address 4DA44C1F Stack: at Microsoft.VisualStudio.Debugger.Clr.NativeDkmClrModuleInstance.ProcF4BC786AEBAC294EE9C4C0BB1B0F56A7(IntPtr, IntPtr ByRef) at Microsoft.VisualStudio.Debugger.Clr.DkmClrModuleInstance.GetMetaDataImport() at Microsoft.IntelliTrace.Concord.MetadataHelper..ctor(Microsoft.VisualStudio.Debugger.Clr.DkmClrModuleInstance) at Microsoft.IntelliTrace.Concord.Integration.CpdeNotifyPointServiceAdapter.InstallBreakpoint(Microsoft.VisualStudio.Debugger.Clr.DkmClrModuleInstance, Microsoft.VisualStudio.Debugger.Interop.Internal.NP_INSTALL_REQUEST)
at Microsoft.IntelliTrace.Concord.Integration.CpdeNotifyPointServiceAdapter.BindToModule(Microsoft.VisualStudio.Debugger.Clr.DkmClrModuleInstance) at Microsoft.IntelliTrace.Concord.IntelliTraceProcessState.AlertModuleLoad(Microsoft.VisualStudio.Debugger.DkmModuleInstance) at Microsoft.IntelliTrace.Concord.NotifyPoints.NotifyPointManager.OnModuleInstanceLoad(Microsoft.VisualStudio.Debugger.DkmModuleInstance, Microsoft.VisualStudio.Debugger.DkmWorkList, Microsoft.VisualStudio.Debugger.DkmEventDescriptorS) at Microsoft.VisualStudio.Debugger.EntryPoint.IDkmModuleInstanceLoadNotification_OnModuleInstanceLoad(IntPtr, IntPtr, IntPtr, IntPtr)

followed by this:

Faulting application name: devenv.exe, version: 12.0.30501.0, time stamp: 0x5361f453 Faulting module name: vsdebugeng.impl.DLL, version: 12.0.30501.0, time stamp: 0x5361f482 Exception code: 0xc0000005 Fault offset: 0x00094c1f Faulting process id: 0x1c9c Faulting application start time: 0x01cfe7cc0cf50465 Faulting application path: C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe Faulting module path: C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Packages\Debugger\vsdebugeng.impl.DLL Report Id: 097b17c6-5438-11e4-8409-001f2904053c

like image 546
Eric Brown - Cal Avatar asked Oct 15 '14 14:10

Eric Brown - Cal


1 Answers

Keep in mind that there is no such thing as a "CorruptedStateException". It is just a collector word, a set of exceptions that the CLR team picked as "excessively nasty". They intentionally do not document what kind of exceptions they put in that set, other than there are "about a dozen" and that they started as Windows SEH exceptions. The only one I know that is definitely in that set is AccessViolationException. The one that crashed VS in your case. Pretty common, as nasty as they come.

The feature was added to .NET 4.0 to help programmers that do what you do, catch-em-all exception handling with catch (Exception). And then letting the program continuing to run. This has a knack for byting badly, they also catch the really nasty exceptions, the kind that they should never catch because they are guaranteed to be unrecoverable. Often unwittingly. The program failure that this causes is very hard to diagnose, it can be a while before the misbehavior is detectable.

I could speculate what other SEH exceptions are in the set. But that just be guesses. Key point is that you don't have to know. Any method with [HandleProcessCorruptedStateExceptions] should be an outer exception handler, activated at thread-entry. Like Main(). And do very little, the kind of thing an SEH handler should do, just let the user know why the program failed and call Environment.FailFast().

So programming catch (Exception) without the attribute is now fine, the CLR will skip it when it looks for a handler. You cannot accidentally swallow the nasty stuff. Your case is perhaps a little different, looks like an add-in without a well-defined thread entrypoint. Move the body of the method with try/catch into another method and omit the attribute on that one. To be called by the method with the attribute, it can now safely assume that it caught one of the nasty ones.

And make sure of course that you don't leave VS running when it catches. The debugger state is blown to pieces, the debug session is most certainly over, the programmer attempting to continue to use it is going to end poorly. So display a message box and fail-fast or rethrow.

like image 100
Hans Passant Avatar answered Sep 18 '22 13:09

Hans Passant