Search code examples
.netexceptioncrashcrash-reports

How to force an application crash when AccessViolationException is detected


We use an automated crash reporting tool (namely http://crashrpt.sourceforge.net) for generating crash reports.

So if a piece of unmanaged code fails by accessing a NULL pointer for example, the application crashes, the crash reporting tool activates and we get usable stack trace for diagnosing and grouping issues.

The problem is that .NET seems to interfere with crash handling in some cases. One sample is the following:

this.Dispatcher.BeginInvoke((ThreadStart)delegate
{
  // Send message to unmanaged control for performing a specific task.
  User32.SendMessage(...);
}, DispatcherPriority.Input);

If the unmanaged component then fails with an access violation, internal .NET methods catch what should actually be a crash as AccessViolationException and rewrap it inside a TargetInvocationException first, then crashes (it would not do that without using method invocation).

This is highly inconvenient, because the native stack information is completely lost. What remains is the following stack, independently of where exactly the unmanaged part has failed:

kernelbase!RaiseException+0x6c
clr!RaiseTheExceptionInternalOnly+0x276
clr!RaiseTheException+0x86
clr!RaiseTheExceptionInternalOnly+0x30a
clr!RealCOMPlusThrow+0x2f
clr!ThrowInvokeMethodException+0xac
clr!RuntimeMethodHandle::InvokeMethod+0xa64
mscorlib_ni+0x2d37b1
mscorlib_ni+0x2cf92a
windowsbase_ni+0xd77b1
windowsbase_ni+0xd768a
windowsbase_ni+0xc2d5c
windowsbase_ni+0xc2c98
mscorlib_ni+0x302346
mscorlib_ni+0x302301
windowsbase_ni+0xc2b9b
windowsbase_ni+0xd640b
windowsbase_ni+0xd65ca
windowsbase_ni+0xd798b
windowsbase_ni+0xd78db
windowsbase_ni+0xd7756
windowsbase_ni+0xd768a
windowsbase_ni+0xd5cae
windowsbase_ni+0xd71e1
user32!InternalCallWinProc+0x23
user32!UserCallWinProcCheckWow+0x100
user32!DispatchMessageWorker+0x3ef
user32!DispatchMessageW+0x10
windowsbase_ni+0xddca8
windowsbase_ni+0xd5636
windowsbase_ni+0xd5325
windowsbase_ni+0xb27d3
presentationframework_ni+0x2721b7
presentationframework_ni+0x271e0f
presentationframework_ni+0x271baa
clr!CallDescrWorkerInternal+0x34
clr!CallDescrWorkerWithHandler+0x6b
clr!MethodDescCallSite::CallTargetWorker+0x152
clr!RunMain+0x1aa
clr!Assembly::ExecuteMainMethod+0x124
clr!SystemDomain::ExecuteMainMethod+0x614
clr!ExecuteEXE+0x4c
clr!_CorExeMainInternal+0xdc
clr!_CorExeMain+0x4d
mscoreei!_CorExeMain+0x10a
mscoree!ShellShim__CorExeMain+0x7d
mscoree!_CorExeMain_Exported+0x8
kernel32!BaseThreadInitThunk+0xe
ntdll!__RtlUserThreadStart+0x72
ntdll!_RtlUserThreadStart+0x1b

How can we prevent that and force the application to crash immediately when the unmanaged component fails?


Solution

  • Try this:

    this.Dispatcher.BeginInvoke((Action) delegate 
    {
        User32.SendMessage(...);
    }, DispatcherPriority.Input);
    

    The application should crash the way you want it to.


    Most of the examples I've seen that call Dispatcher.BeginInvoke() with an anonymous delegate use an Action.


    Why does this happen?

    It seems that the CLR code, way down in:

    at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
    at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
    at System.Windows.Threading.DispatcherOperation.InvokeImpl()
    

    invokes an Action directly, most other delegates are invoked using reflection.

    The reflection mechanism will wrap exceptions in a TargetInvocationException.

    See this answer to another question to explain.


    Other special case delegates which will not wrap exceptions are: DispatcherOperationCallback and SendOrPostCallback, though to work they have to be called with a single argument.

    this.Dispatcher.BeginInvoke(DispatcherPriority.Input,
        (SendOrPostCallback)(delegate(object o)
        {
            throw new AccessViolationException(o.ToString());
        }), "test");