none
surviving thread crashes in unmanaged hosted clr RRS feed

  • Question

  • I am trying to write an application in unmanaged code that would host clr, and load any client applications in it, if there are any exceptions in client applicatoin, the host would gracefully shut it down and report any issues. for this I have a sample code library in C# that throws an exception like this ...

     public static int StartUp(string arguments)
     {
           Console.WriteLine("Started exception thrower with args {0}", arguments);
           Thread workerThread = new Thread(() => 
                {
                    Console.WriteLine("Starting a thread, doing some important work");
                    Thread.Sleep(1000);
                    throw new ApplicationException();
                }
             );
             workerThread.Start();
             workerThread.Join();
             Console.WriteLine("this should never print");
            return 11;
        }


     then i have native win32 console app like this ..

    int _tmain(int argc, _TCHAR* argv[])
    {
        ICLRMetaHost *pMetaHost       = NULL;
        HRESULT hr; 
        ICLRRuntimeInfo *runtimeInfo = NULL;    
        __try
        {
            hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
            hr = pMetaHost->GetRuntime(L"v4.0.30319",IID_ICLRRuntimeInfo,(LPVOID*)&runtimeInfo);
            ICLRRuntimeHost *runtimeHost  = NULL;
            hr = runtimeInfo->GetInterface(CLSID_CLRRuntimeHost,IID_ICLRRuntimeHost, (LPVOID*)&runtimeHost);    
            ICLRControl* clrControl = NULL;
            hr = runtimeHost->GetCLRControl(&clrControl);
            ICLRPolicyManager *clrPolicyManager = NULL;
            clrControl->GetCLRManager(IID_ICLRPolicyManager, (LPVOID*)&clrPolicyManager);
            clrPolicyManager->SetDefaultAction(OPR_ThreadAbort,eUnloadAppDomain);   
            hr = runtimeHost->Start();
            DWORD returnVal = NULL;         
            hr = runtimeHost->ExecuteInDefaultAppDomain(L"ExceptionThrower.dll",L"ExceptionThrower.MainExceptionThrower",L"StartUp",L"test",&returnVal);        
            runtimeHost->Release();
        }
        __except(1)
        {
            wprintf(L"\n Error thrown %d",e);
        }
        return 0;
    }



    Issue is that if i use the above code, the host would complete running the managed code (the line "this should never print" would end up printing) If i remove the clrPolicyManager->SetUnhandledExceptionPolicy(eHostDeterminedPolicy), then the host process would crash.
    can anything be done in the unmanaged host that it could gracefully remove the errant app from runtime and continue working ?


    • Edited by seeker_123 Wednesday, October 26, 2011 6:38 PM
    Wednesday, October 26, 2011 6:37 PM

Answers

  • When a thread throws an exception, only handlers in that thread's call stack are considered.

     

    The reason it works for managed threads is because the CLR sticks a handler at the top level, which will invoke the unhandled exception handler. Unmanaged threads do not have this top-level handler, so they don't forward their exceptions to the unhandled exception handler. So I don't think it is able to catch a unhandled managed exception in unmanaged code. But it is able to marshal a handled exception to native code.

     

    While you can get CLR exceptions as native SEH in a native UnhandledExceptionFilter(), you will not be able to access managed exception information - simply because only the CLR itself can access that information.If you are chaining a SEH  UnhandledExceptionFilter() in your mixed application - which you should only do for good reason - there are two thighs to take into consideration:

    • propelry chain your filter as a "good Win32 citizen" and call the previously set filter before doing your processing
    • it is imperative not to interfere with the CLR SEH exceptions and always return EXCEPTION_CONTINUE_SEARCH for such exceptions - as for any exceptions you are not handling yourself: otherwise you can easily put the CLR in an undefined state

     

    More information, you can read this article:

    .NET Interop and exception handling in mixed applications


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Paul Zhou Friday, November 4, 2011 5:13 AM
    Tuesday, November 1, 2011 5:52 AM

All replies

  • Hi,

    I don't see "clrPolicyManager->SetUnhandledExceptionPolicy(eHostDeterminedPolicy)" in your code sample. Why do you need to remove this code line?

    Moreover, about host CLR, you can refer to:Host CLR

    I hope this can help you.

     


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, October 28, 2011 5:38 AM
  • i removed that because that makes the code swallow the exception and continue execution, which is not what i want. I just want the clr to unload the app domain, or disable the clr or anything except crashing out.

    Currently the process crashes without giving a chance to log anything , or recover in any shape or fashion

    Friday, October 28, 2011 1:46 PM
  • SetUnhandledExceptionPolicy(eHostDeterminedPolicy specifies the behavior of the common language runtime (CLR) when an unhandled exception occurs. The host can change this behavior by setting the policy value to eHostDeterminedPolicy. This value allows the host to implement its own default behavior, as with earlier versions of the CLR. In your case, it implements the behavior as .NET Framework 2.0. In the .NET Framework version 2.0, the common language runtime allows most unhandled exceptions in threads to proceed naturally. So if you SetUnhandledExceptionPolicy, the application won't be crashed. If you remove it, it would be crashed because a unhandled exception threw.

     

    The "this should never print" line should be printed because the code line is running in a main thread, the worker thread in running in a separate thread, if the process hasn't been closed, the two threads would keep running.

     

    I think you'd better handle the exception in managed code, when catching such an exception, unload the current appdomain.

     

    ICLRPolicyManager::SetUnhandledExceptionPolicy Method

    Exceptions in Managed Threads


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, October 31, 2011 5:57 AM
  • well its a plugin system, so the managed code might not be in my control..

    also i am on version .net 4.0, and could go to 4.5 if it fixes this behavior...

    I would think that an ideal behavior would be to somehow inform some level of code that such an exeption has happened with in an appdomain, and provide for some recovery or error logging options...

    so to summarize,

    option # 1: fallback to legacy behavior, where threading exceptions would be silently ignored and the code would proceed naturally. This ofcourse can be worse than process crash, since it can result in fake success.

    option #2 : the pocess crashes, taking everything down with it...

    and there is no way, not even in unmanaged code, not even by customizing parts of CLR that this behavior can be changed.

    can microsoft confirm this ?

     

     

    Monday, October 31, 2011 2:49 PM
  • When a thread throws an exception, only handlers in that thread's call stack are considered.

     

    The reason it works for managed threads is because the CLR sticks a handler at the top level, which will invoke the unhandled exception handler. Unmanaged threads do not have this top-level handler, so they don't forward their exceptions to the unhandled exception handler. So I don't think it is able to catch a unhandled managed exception in unmanaged code. But it is able to marshal a handled exception to native code.

     

    While you can get CLR exceptions as native SEH in a native UnhandledExceptionFilter(), you will not be able to access managed exception information - simply because only the CLR itself can access that information.If you are chaining a SEH  UnhandledExceptionFilter() in your mixed application - which you should only do for good reason - there are two thighs to take into consideration:

    • propelry chain your filter as a "good Win32 citizen" and call the previously set filter before doing your processing
    • it is imperative not to interfere with the CLR SEH exceptions and always return EXCEPTION_CONTINUE_SEARCH for such exceptions - as for any exceptions you are not handling yourself: otherwise you can easily put the CLR in an undefined state

     

    More information, you can read this article:

    .NET Interop and exception handling in mixed applications


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Paul Zhou Friday, November 4, 2011 5:13 AM
    Tuesday, November 1, 2011 5:52 AM
  • the only thread that i am creating in my code is managed code, rest is running on the main thread created in the unmanaged host. Is the thread created by user code in managed code unmanaged ?

    Tuesday, November 1, 2011 9:58 PM
  • The exception is threw from a managed thread, the main thread(the host thread) is a unmanaged thread.

    As said, you will not be able to get managed exception information in a native handler.


    Paul Zhou [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, November 2, 2011 4:32 AM