/// <summary>
 /// Destroy the AppDomain.
 /// </summary>
 private void DestroyDomain(bool disposing)
 {
     Console.WriteLine("Unloading AppDomain '" +
                       mAppDomain.FriendlyName + "', id=" + mAppDomain.Id +
                       ", disposing=" + disposing);
     if (mPluginLoader != null)
     {
         mPluginLoader.Dispose();
         mPluginLoader = null;
     }
     if (mAppDomain != null)
     {
         // We can't simply invoke AppDomain.Unload() from a finalizer.
         // The unload is handled by a thread that won't run at the
         // same time as the finalizer thread, so if we got here
         // through finalization we will deadlock.  Fortunately the
         // runtime sees the situation and throws an exception out of
         // Unload().
         //
         // If we don't have a finalizer, and we forget to make an
         // explicit cleanup call, the AppDomain will stick around.
         //
         // So we use a workaround from
         // https://stackoverflow.com/q/4064749/294248 and invoke it
         // asynchronously.
         if (disposing)
         {
             AppDomain.Unload(mAppDomain);
         }
         else
         {
             new Action <AppDomain>(AppDomain.Unload).BeginInvoke(
                 mAppDomain, null, null);
         }
         mAppDomain = null;
     }
 }
Beispiel #2
0
        /// <summary>
        /// Creates a new AppDomain.  If our plugin is just executing
        /// pre-compiled code we can lock the permissions down, but if
        /// it needs to dynamically compile code we need to open things up.
        /// </summary>
        /// <param name="appDomainName">The "friendly" name.</param>
        /// <param name="cap">Permission set.</param>
        public void CreateDomain(string appDomainName, DomainCapabilities cap)
        {
            if (mAppDomain != null)
            {
                throw new Exception("Domain already created");
            }

            PermissionSet permSet;

            if (LEASE_TEST)
            {
                // Use this when overriding InitializeLifetimeService in
                // PluginLoader.  See the comments there for more details.
                permSet = new PermissionSet(PermissionState.Unrestricted);
            }
            else if (cap == DomainCapabilities.ALLOW_DYNAMIC)
            {
                // Set the permissions in a way that allows the plugin to
                // run the CSharpCodeProvider.  It looks like the compiler
                // requires "FullTrust", which limits our options here.
                // TODO: see if we can narrow this down.
                permSet = new PermissionSet(PermissionState.Unrestricted);
            }
            else
            {
                // Start with everything disabled.
                permSet = new PermissionSet(PermissionState.None);
                // Allow code execution.
                permSet.AddPermission(new SecurityPermission(
                                          SecurityPermissionFlag.Execution));

                // Allow changes to Remoting stuff.  Without this, we can't
                // register our ISponsor.  TODO: figure out if there's a better way.
                permSet.AddPermission(new SecurityPermission(
                                          SecurityPermissionFlag.RemotingConfiguration));

                // Allow read-only file access, but only in the plugin directory.
                // This is necessary to allow PluginLoader to load the assembly.
                FileIOPermission fp = new FileIOPermission(
                    FileIOPermissionAccess.Read |
                    FileIOPermissionAccess.PathDiscovery,
                    mPluginPath);
                permSet.AddPermission(fp);
            }

            // Configure the AppDomain.  Setting the ApplicationBase
            // property is apparently very important, as it mitigates the
            // risk of certain exploits from untrusted plugin code.
            AppDomainSetup adSetup = new AppDomainSetup();

            adSetup.ApplicationBase = mPluginPath;

            //string hostAppBase =
            //    AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

            // Create the AppDomain.  We're not passing in Evidence or
            // StrongName[].  Not sure that's important.
            mAppDomain = AppDomain.CreateDomain("Plugin AppDomain",
                                                null, adSetup, permSet);

            Console.WriteLine("Created AppDomain '" + appDomainName +
                              "', id=" + mAppDomain.Id);

            // Create a PluginLoader in the remote AppDomain.  The local
            // object is actually a proxy.
            PluginLoader pl = (PluginLoader)mAppDomain.CreateInstanceAndUnwrap(
                typeof(PluginLoader).Assembly.FullName,
                typeof(PluginLoader).FullName);

            // Wrap it so it doesn't disappear on us.
            mPluginLoader = new Sponsor <PluginLoader>(pl);
        }