I have discovered a scenario where my .Net application will crash unexpectedly without raising any exceptions. I would like that, at least, AppDomain.UnhandledException
worked in this case, in order to enable me at least to log the error and present the user with some information.
In this scenario, I have an .Net assembly (let's call it A) with an interop call to a native DLL (which we will call B). B creates a thread and throws; Without anyone to catch the exception, I'd expect it to go all the way up the stack, back into my managed application, and then finally become an unhandled exception.
At this point I would expect the OS to hand the control back to .Net, which would call AppDomain.UnhandledException
and, with that, my application would end. However, the call is never made.
Below I included enough information to reproduce the issue. It can be ignored.
Program.cs
internal class Program
{
public static void Main()
{
AppDomain.CurrentDomain.UnhandledException += _currentDomainUnhandledException;
try
{
BugDllInterop.ErrorMethod(0);
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.GetType().Name);
}
Console.WriteLine("Clean exit.");
}
private static void _currentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Exception trapped.");
}
}
BugDllInterop.cs
public static class BugDllInterop
{
private const string BUG_DLL = "InteropExceptions.BugDll.dll";
[DllImport(BUG_DLL, CallingConvention = CallingConvention.Cdecl)]
public extern static void ErrorMethod(int i);
}
BugDll.h
// INCLUSION GUARD
#pragma once
#define DllExport __declspec(dllexport)
extern "C"
{
DllExport void ErrorMethod(int i);
}
BugDll.cpp
// HEADER /////////////////////////////////////////////////////////////////////
#include "BugDll.h"
// LIBRARIES //////////////////////////////////////////////////////////////////
#include <windows.h>
#include <fstream>
#include <iostream>
#include <time.h>
using namespace std;
// FUNCTIONS //////////////////////////////////////////////////////////////////
DWORD WINAPI threadMethod(LPVOID lpParameter)
{
throw 0;
return 0;
}
void ErrorMethod(int i)
{
DWORD myThreadID;
HANDLE myHandle = CreateThread(0, 0, threadMethod, 0, 0, &myThreadID);
WaitForSingleObject(myHandle, 3000);
CloseHandle(myHandle);
}
Again, my desired is just that the AppDomain.UnhandledException
event is raised. Of course, if anyone knows how to properly handle the exception in order to keep the application alive, it would be even better.
You can't catch and manage exception thrown from another unmanaged thread.
When a method throws an exception the CLR will search for a handler only in the thread where the exception has been thrown. It's even understandable because the call stack of a thread begins with the thread itself.
You have a root exception handler because the CLR puts a handler at the top level (the one will invoke your filter) but this isn't true for unmanaged threads so their exception can't be forwarded.
The only solution for this situation is to catch exception in the thread where they are originated. If your thread function can throw an exception then add a catch there. Anyway not on the managed side. Managed/unmanaged boundaries are pretty thick here.
You may like to read this nice article about exception handling: http://www.microsoft.com/msj/0197/exception/exception.aspx
来源:https://stackoverflow.com/questions/10282012/exception-on-native-thread-crashes-net-application-without-exception