hosting clr and catching threading exceptions

前端 未结 4 1848
梦毁少年i
梦毁少年i 2021-02-07 19:22

I am trying to write an plugin system that can load managed plugins. The host should be able to unload the plugins if there are any exceptions. for my poc I have a sample code

相关标签:
4条回答
  • 2021-02-07 19:52

    First of all, if you want to prevent application crash with the code above, you'll need to use SetUnhandledExceptionFilter, like this:

    LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionInfo)
    {
        // do something useful
        return EXCEPTION_EXECUTE_HANDLER; // prevent crash
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
            ...
    }
    

    But this may not be what you really want. One solution (as proposed by Polity I believe) is to create an intermediary AppDomain that can catch easily all unhandled exceptions. You can do that in C#, like this:

    public class PluginVerifier
    {
        public static int CheckPlugin(string arguments)
        {
            AppDomain appDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
            appDomain.UnhandledException += AppDomainUnhandledException;
            object obj = appDomain.CreateInstanceAndUnwrap("ExceptionThrower", "ExceptionThrower.MainExceptionThrower");
            object ret = obj.GetType().InvokeMember("Startup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, obj, new object[] { arguments });
            AppDomain.Unload(appDomain);
            return (int)ret;
        }
    
        private static void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            AppDomain appDomain = (AppDomain)sender;
            // the following will prevent "this should never print" to happen
            AppDomain.Unload(appDomain);
        }
    }
    

    For this to be able to work however, you need to do two changes to your plugin classes:

    • they must derive from MarshalByRefObject
    • the plugin method must not be static (static methods call do not go through AppDomain filter)

    So your class would be written like this:

    public class MainExceptionThrower: MarshalByRefObject
    {
        public int StartUp(string arguments)
        {
        ...
        }
     }
    

    If you do this, you can remove the calls to SetUnhandledExceptionPolicy, SetActionOnFailure, or SetDefaultAction, and just replace the bootstrap code like this:

        hr = runtimeHost->ExecuteInDefaultAppDomain(L"PluginSystem.dll", L"PluginSystem.PluginVerifier", L"CheckPlugin", L"test", &returnVal);        
    

    If you try this with your Startup code above, this call will return hr=0x80131604, which is COR_E_TARGETINVOCATION (TargetInvocationException).

    0 讨论(0)
  • 2021-02-07 19:57

    You can start a new AppDomain specifically for each given plugin and launch it inside. See http://msdn.microsoft.com/en-us/library/ms164323.aspx

    Each AppDomain is an isolated environment where code can execute. Exceptions occuring in one AppDomain can be isolated from th rest. See: http://msdn.microsoft.com/en-us/library/system.appdomain(v=VS.100).aspx

    0 讨论(0)
  • 2021-02-07 19:58

    You brought up a very interesting question, thanks for that.

    I suppose this article will be helpful enough: http://etutorials.org/Programming/programming+microsoft+visual+c+sharp+2005/Part+III+More+C+Language/Chapter+9+Exception+Handling/Unhandled+Exceptions/

    0 讨论(0)
  • 2021-02-07 20:18

    Looks like adding following together with SetDefaultAction resolves the crash:

    clrPolicyManager->SetUnhandledExceptionPolicy(EClrUnhandledException::eHostDeterminedPolicy);
    
    0 讨论(0)
提交回复
热议问题