How to force an application crash when AccessViolationException is detected

匿名 (未验证) 提交于 2019-12-03 09:02:45

问题:

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?

回答1:

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"); 


回答2:

Use below code to close the application after getting the exception.

Environment.Exit(1);     

Exit needs a parameter called exitcode. If exitcode=0 means there was no error. Supply a non-zero exit code to to reflect an error.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!