private void CreateAppDomain()
{
// Locking s_AppDomains must happen in a CER so we don't orphan a lock that gets taken by AppDomain.DomainUnload.
bool lockHeld = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
try { }
finally
{
Monitor.Enter(s_AppDomains.SyncRoot);
lockHeld = true;
}
if (s_CleanedUp)
{
throw new InvalidOperationException(SR.GetString(SR.net_cant_perform_during_shutdown));
}
// Create singleton.
if (s_AppDomainInfo == null)
{
s_AppDomainInfo = new AppDomainSetup();
s_AppDomainInfo.DisallowBindingRedirects = true;
s_AppDomainInfo.DisallowCodeDownload = true;
NamedPermissionSet perms = new NamedPermissionSet("__WebProxySandbox", PermissionState.None);
perms.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
}
// If something's already in s_ExcessAppDomain, try to dislodge it again.
AppDomain excessAppDomain = s_ExcessAppDomain;
if (excessAppDomain != null)
{
TimerThread.GetOrCreateQueue(0).CreateTimer(new TimerThread.Callback(CloseAppDomainCallback), excessAppDomain);
throw new InvalidOperationException(SR.GetString(SR.net_cant_create_environment));
}
appDomainIndex = s_NextAppDomainIndex++;
try { }
finally
{
//
s_ExcessAppDomain = AppDomain.CreateDomain(c_appDomainName, null, s_AppDomainInfo);
try
{
s_AppDomains.Add(appDomainIndex, s_ExcessAppDomain);
// This indicates to the finally and the finalizer that everything succeeded.
scriptDomain = s_ExcessAppDomain;
}
finally
{
// ReferenceEquals has a ReliabilityContract.
if (object.ReferenceEquals(scriptDomain, s_ExcessAppDomain))
{
s_ExcessAppDomain = null;
}
else
{
// Something failed. Leave the domain in s_ExcessAppDomain until we can get rid of it. No
// more AppDomains can be created until we do. In the mean time, keep attempting to get the
// TimerThread to remove it. Also, might as well remove it from the hash if it made it in.
try
{
s_AppDomains.Remove(appDomainIndex);
}
finally
{
// Can't call AppDomain.Unload from a user thread (or in a lock).
TimerThread.GetOrCreateQueue(0).CreateTimer(new TimerThread.Callback(CloseAppDomainCallback), s_ExcessAppDomain);
}
}
}
}
}
finally
{
if (lockHeld)
{
Monitor.Exit(s_AppDomains.SyncRoot);
}
}
}