Exceptions to unmanaged threads in .NET.

How do I handle situations where my application crashes using a callback before completion?

.NET handlers do not work in the following scenario, is SetUnhandledExceptionHandler the right choice? The flaws seem to be discussed below.

Scenario

I want to answer all cases of application termination with a message and an error message for our service in our .net application.

However, I have a WPF application in which our two testers receive unhandled exceptions that bypass:

  • AppDomain.UnhandledException (most important)
  • Application.ThreadException
  • Dispatcher.UnhandledException

They are marked with SecuirtyCritical and HandleProcessCorruptedStateExceptions . legacyCorruptedStateExceptionsPolicy set to true in app.config

My two examples in the wild

  • VirtualBox running widows10 runs inside some vboxd3d.dll when initializing WPF somewhere (disables vbox 3d accel "fix it")
  • Win8 machine with a suspicious option "run on the A / B graphic card" in the system context menu, a crash somewhere (: /) during WPF startup, but only when using anti-cracking tools.

In any case, when you live, the application must respond to these failures until completion .

, PInvoked .net:

test.dll

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

DWORD WINAPI myThread(LPVOID lpParameter)
{
    long testfail = *(long*)(-9022);
    return 1;
}

extern "C" __declspec(dllexport) void test()
{
    DWORD tid;
    HANDLE myHandle = CreateThread(0, 0, myThread, NULL, 0, &tid);
    WaitForSingleObject(myHandle, INFINITE);
}

app.exe

class TestApp
{
    [DllImport("kernel32.dll")]
    static extern FilterDelegate SetUnhandledExceptionFilter(FilterDelegate lpTopLevelExceptionFilter);

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    delegate int FilterDelegate(IntPtr exception_pointers);

    static int Win32Handler(IntPtr nope)
    {
        MessageBox.Show("Native uncaught SEH exception"); // show + report or whatever
        Environment.Exit(-1); // exit and avoid WER etc
        return 1; // thats EXCEPTION_EXECUTE_HANDLER, although this wont be called due to the previous line
    }

    [DllImport("test.dll")]
    static extern void test();

    [STAThread]
    public static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        SetUnhandledExceptionFilter(Win32Handler);
        test(); // This is caught by Win32Handler, not CurrentDomain_UnhandledException
    }
    [SecurityCritical, HandleProcessCorruptedStateExceptions ]
    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Exception ex = e.ExceptionObject as Exception;
        MessageBox.Show(ex.ToString()); // show + report or whatever
        Environment.Exit(-1); // exit and avoid WER etc
    }
}

vboxd3d.dll WPF, , , WCF Dispatcher WinForms ().

  • , , , , - , , 100 , , , .
    • vbox3d.dll clr.dll.
    • , , kernel32, . dll, , , . - , , , clr ...
    • . "" . . , SO ...
+4
3

:

SetUnhandledExceptionFilter(Win32Handler);

, , :

FilterDelegate del = new FilterDelegate(Win32Handler);
SetUnhandledExceptionFilter(del);

, GC native- > thunk, . :

SetUnhandledExceptionFilter(Win32Handler);
GC.Collect();
native_crash_on_unmanaged_thread();

, , kernel32.dll, . , GC :

public class Program
{
    static FilterDelegate mdel;
    public static void Main(string[] args)
    {
        FilterDelegate del = new FilterDelegate(Win32Handler);
        SetUnhandledExceptionFilter(del);
        GC.KeepAlive(del);  // do not collect "del" in this scope (main)
        // You could also use mdel, which I dont believe is collected either
        GC.Collect();
        native_crash_on_unmanaged_thread(); 
    }
}

; , .

+2

, , .

P/Invoking , . ++/CLI , ++ , ++/CLI.

: " ?"

-, , .

- - ( dll), stl, , CLI stl. - , stl, , , stl , , . : " - , #pragma managed / #pragma unmanaged , ". , , . , , ( ) , .

, , , , , .

:

try {
    // a bunch of set up code that you don't need to
    // see reduced to this:
    SomeImageType *outImage = GetImage();
    // I was having problems with the heap getting mangled
    // so heapcheck() is conditional macro that calls [_heapchk()][1]
    heapcheck();
    return outImage;
}
catch (std::bad_alloc &) {
    throw MyLib::MyLibNoMemory();
}
catch (MyLib::MyLibFailure &err)
{
    throw err;
}
catch (const char* msg)
{
    // seriously, some code throws a string.
    throw msg;
}
catch (...) {
    throw MyLib::MyLibFailure(MyKib::MyFailureReason::kUnknown2);
}
0

, , , , . .

, . , . , - , .

And as a last resort, when your processes begin to check whether they have closed correctly. If not, then you can report a bad shutdown. This will be useful if the whole computer dies.

-1
source

All Articles