Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / xsp / System / Web / Hosting / ProcessHost.cs / 1599808 / ProcessHost.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.Hosting { using System; using System.Collections; using System.Collections.Generic; using System.Configuration; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Remoting; using System.Security; using System.Security.Permissions; using System.Threading; using System.Web; using System.Web.Configuration; using System.Web.Util; [ComImport, Guid("0ccd465e-3114-4ca3-ad50-cea561307e93"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IProcessHost { void StartApplication( [In, MarshalAs(UnmanagedType.LPWStr)] String appId, [In, MarshalAs(UnmanagedType.LPWStr)] String appPath, [MarshalAs(UnmanagedType.Interface)] out Object runtimeInterface); void ShutdownApplication([In, MarshalAs(UnmanagedType.LPWStr)] String appId); void Shutdown(); void EnumerateAppDomains( [MarshalAs(UnmanagedType.Interface)] out IAppDomainInfoEnum appDomainInfoEnum); } // // App domain protocol manager // Note that this doesn't provide COM interop // public interface IAdphManager { void StartAppDomainProtocolListenerChannel( [In, MarshalAs(UnmanagedType.LPWStr)] String appId, [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, IListenerChannelCallback listenerChannelCallback); void StopAppDomainProtocolListenerChannel( [In, MarshalAs(UnmanagedType.LPWStr)] String appId, [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, int listenerChannelId, bool immediate); void StopAppDomainProtocol( [In, MarshalAs(UnmanagedType.LPWStr)] String appId, [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, bool immediate); } [ComImport, Guid("1cc9099d-0a8d-41cb-87d6-845e4f8c4e91"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IPphManager { void StartProcessProtocolListenerChannel( [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, IListenerChannelCallback listenerChannelCallback); void StopProcessProtocolListenerChannel( [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, int listenerChannelId, bool immediate); void StopProcessProtocol( [In, MarshalAs(UnmanagedType.LPWStr)] String protocolId, bool immediate); } [ComImport, Guid("9d98b251-453e-44f6-9cec-8b5aed970129"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IProcessHostIdleAndHealthCheck { [return: MarshalAs(UnmanagedType.Bool)] bool IsIdle(); void Ping(IProcessPingCallback callback); } [ComImport, Guid("5BC9C234-6CD7-49bf-A07A-6FDB7F22DFFF"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IAppDomainInfo { [return: MarshalAs(UnmanagedType.BStr)] string GetId(); [return: MarshalAs(UnmanagedType.BStr)] string GetVirtualPath(); [return: MarshalAs(UnmanagedType.BStr)] string GetPhysicalPath(); [return: MarshalAs(UnmanagedType.I4)] int GetSiteId(); [return: MarshalAs(UnmanagedType.Bool)] bool IsIdle(); } [ComImport, Guid("F79648FB-558B-4a09-88F1-1E3BCB30E34F"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IAppDomainInfoEnum { [return: MarshalAs(UnmanagedType.Interface)] IAppDomainInfo GetData(); [return: MarshalAs(UnmanagedType.I4)] int Count(); [return: MarshalAs(UnmanagedType.Bool)] bool MoveNext(); void Reset(); } public class AppDomainInfoEnum : IAppDomainInfoEnum { private AppDomainInfo[] _appDomainInfos; private int _curPos; internal AppDomainInfoEnum(AppDomainInfo[] appDomainInfos) { _appDomainInfos = appDomainInfos; _curPos = -1; } public int Count() { return _appDomainInfos.Length; } public IAppDomainInfo GetData() { return _appDomainInfos[_curPos]; } public bool MoveNext() { _curPos++; if (_curPos >= _appDomainInfos.Length) { return false; } return true; } public void Reset() { _curPos = -1; } } public class AppDomainInfo : IAppDomainInfo { private string _id; private string _virtualPath; private string _physicalPath; private int _siteId; private bool _isIdle; internal AppDomainInfo(string id, string vpath, string physPath, int siteId, bool isIdle) { _id = id; _virtualPath = vpath; _physicalPath = physPath; _siteId = siteId; _isIdle = isIdle; } public string GetId() { return _id; } public string GetVirtualPath() { return _virtualPath; } public string GetPhysicalPath() { return _physicalPath; } public int GetSiteId() { return _siteId; } public bool IsIdle() { return _isIdle; } } ///////////////////////////////////////////////////////////////////////////// // New for Dev10 [ComImport, Guid("AE54F424-71BC-4da5-AA2F-8C0CD53496FC"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IApplicationPreloadManager { [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Util", Justification="Name must match IIS COM interface.")] [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="0#Util", Justification="Name must match IIS COM interface.")] void SetApplicationPreloadUtil( [In, MarshalAs(UnmanagedType.Interface)] IApplicationPreloadUtil preloadUtil); void SetApplicationPreloadState( [In, MarshalAs(UnmanagedType.LPWStr)] string context, [In, MarshalAs(UnmanagedType.LPWStr)] string appId, [In, MarshalAs(UnmanagedType.Bool)] bool enabled); } [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Util", Justification="Name must match IIS COM interface.")] [ComImport, Guid("940D8ADD-9E40-4475-9A67-2CDCDF57995C"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IApplicationPreloadUtil { [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="1#", Justification="Parameter kind must match IIS COM interface.")] [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="2#", Justification="Parameter kind must match IIS COM interface.")] [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="3#", Justification="Parameter kind must match IIS COM interface.")] void GetApplicationPreloadInfo( [In, MarshalAs(UnmanagedType.LPWStr)] string context, [Out, MarshalAs(UnmanagedType.Bool)] out bool enabled, [Out, MarshalAs(UnmanagedType.BStr)] out string startupObjType, [Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] parametersForStartupObj); void ReportApplicationPreloadFailure( [In, MarshalAs(UnmanagedType.LPWStr)] string context, [In, MarshalAs(UnmanagedType.U4)] int errorCode, [In, MarshalAs(UnmanagedType.LPWStr)] string errorMessage); } ///public sealed class ProcessHost : MarshalByRefObject, IProcessHost, IAdphManager, // process protocol handlers manager IPphManager, // appdomain protocol handlers manager IProcessHostIdleAndHealthCheck, IApplicationPreloadManager { private static Object _processHostStaticLock = new Object(); private static ProcessHost _theProcessHost; private IProcessHostSupportFunctions _functions; private ApplicationManager _appManager; private ProtocolsSection _protocolsConfig; // process protocol handlers by prot id private Hashtable _protocolHandlers = new Hashtable(); private IApplicationPreloadUtil _preloadUtil = null; private System.Threading.Semaphore _preloadingThrottle = null; private ProtocolsSection ProtocolsConfig { get { if (_protocolsConfig == null) { lock (this) { if (_protocolsConfig == null) { if (HttpConfigurationSystem.IsSet) { _protocolsConfig = RuntimeConfig.GetRootWebConfig().Protocols; } else { Configuration c = WebConfigurationManager.OpenWebConfiguration(null); _protocolsConfig = (ProtocolsSection) c.GetSection("system.web/protocols"); } } } } return _protocolsConfig; } } // ctor only called via GetProcessHost private ProcessHost(IProcessHostSupportFunctions functions) { try { // remember support functions _functions = functions; // pass them along to the HostingEnvironment in the default domain HostingEnvironment.SupportFunctions = functions; // create singleton app manager _appManager = ApplicationManager.GetApplicationManager(); // For M3 we get the throttling limit from the registry. // Dev10\Beta1 work item 543420 is to investigate whether we need to get rid of the throttling int maxPreloadConcurrency = (int)Misc.GetAspNetRegValue(null, "MaxPreloadConcurrency", 0); if (maxPreloadConcurrency > 0) { _preloadingThrottle = new System.Threading.Semaphore(maxPreloadConcurrency, maxPreloadConcurrency); } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Cant_Create_Process_Host)}); Debug.Trace("internal", "ProcessHost::ctor failed with " + e.GetType().FullName + ": " + e.Message + "\r\n" + e.StackTrace); } throw; } } // ValidateType // // Validate and Get the Type that is sent in // // Note: Because ProtocolElement is outside of our assembly we need to do // that here, and because of that we need to hardcode the property // names!! // private Type ValidateAndGetType( ProtocolElement element, string typeName, Type assignableType, string elementPropertyName ) { Type handlerType; try { handlerType = Type.GetType(typeName, true /*throwOnError*/); } catch (Exception e) { PropertyInformation propInfo = null; string source = String.Empty; int lineNum = 0; if (element != null && null != element.ElementInformation) { propInfo = element.ElementInformation.Properties[elementPropertyName]; if (null != propInfo) { source = propInfo.Source; lineNum = propInfo.LineNumber; } } throw new ConfigurationErrorsException( e.Message, e, source, lineNum); } ConfigUtil.CheckAssignableType( assignableType, handlerType, element, elementPropertyName); return handlerType; } private Type GetAppDomainProtocolHandlerType(String protocolId) { Type t = null; try { // get app domaoin protocol handler type from config ProtocolElement configEntry = ProtocolsConfig.Protocols[protocolId]; if (configEntry == null) throw new ArgumentException(SR.GetString(SR.Unknown_protocol_id, protocolId)); t = ValidateAndGetType( configEntry, configEntry.AppDomainHandlerType, typeof(AppDomainProtocolHandler), "AppDomainHandlerType" ); } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Invalid_AppDomain_Prot_Type)} ); } } return t; } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)] public override Object InitializeLifetimeService() { return null; // never expire lease } // called from ProcessHostFactoryHelper to get ProcessHost internal static ProcessHost GetProcessHost(IProcessHostSupportFunctions functions) { if (_theProcessHost == null) { lock (_processHostStaticLock) { if (_theProcessHost == null) { _theProcessHost = new ProcessHost(functions); } } } return _theProcessHost; } internal static ProcessHost DefaultHost { get { return _theProcessHost; // may be null } } internal IProcessHostSupportFunctions SupportFunctions { get { return _functions; } } // // IProcessHostProcessProtocolManager interface implementation // // starts process protocol handler on demand public void StartProcessProtocolListenerChannel(String protocolId, IListenerChannelCallback listenerChannelCallback) { try { if (protocolId == null) throw new ArgumentNullException("protocolId"); // validate protocol id ProtocolElement configEntry = ProtocolsConfig.Protocols[protocolId]; if (configEntry == null) throw new ArgumentException(SR.GetString(SR.Unknown_protocol_id, protocolId)); ProcessProtocolHandler protocolHandler = null; Type protocolHandlerType = null; protocolHandlerType = ValidateAndGetType( configEntry, configEntry.ProcessHandlerType, typeof(ProcessProtocolHandler), "ProcessHandlerType" ); lock (this) { // lookup or create protocol handler protocolHandler = _protocolHandlers[protocolId] as ProcessProtocolHandler; if (protocolHandler == null) { protocolHandler = (ProcessProtocolHandler)Activator.CreateInstance(protocolHandlerType); _protocolHandlers[protocolId] = protocolHandler; } } // call the handler to start listenerChannel if (protocolHandler != null) { protocolHandler.StartListenerChannel(listenerChannelCallback, this); } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Invalid_Process_Prot_Type)} ); } throw; } } public void StopProcessProtocolListenerChannel(String protocolId, int listenerChannelId, bool immediate) { try { if (protocolId == null) throw new ArgumentNullException("protocolId"); ProcessProtocolHandler protocolHandler = null; lock (this) { // lookup protocol handler protocolHandler = _protocolHandlers[protocolId] as ProcessProtocolHandler; } // call the handler to stop listenerChannel if (protocolHandler != null) { protocolHandler.StopListenerChannel(listenerChannelId, immediate); } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Stop_Listener_Channel)} ); } throw; } } public void StopProcessProtocol(String protocolId, bool immediate) { try { if (protocolId == null) throw new ArgumentNullException("protocolId"); ProcessProtocolHandler protocolHandler = null; lock (this) { // lookup and remove protocol handler protocolHandler = _protocolHandlers[protocolId] as ProcessProtocolHandler; if (protocolHandler != null) { _protocolHandlers.Remove(protocolId); } } if (protocolHandler != null) { protocolHandler.StopProtocol(immediate); } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Stop_Process_Prot)} ); } throw; } } // // IAppDomainProtocolManager // // starts app domain protocol handler on demand (called by process protocol handler public void StartAppDomainProtocolListenerChannel(String appId, String protocolId, IListenerChannelCallback listenerChannelCallback) { try { if (appId == null) throw new ArgumentNullException("appId"); if (protocolId == null) throw new ArgumentNullException("protocolId"); ISAPIApplicationHost appHost = CreateAppHost(appId, null); // get app domaoin protocol handler type from config Type handlerType = GetAppDomainProtocolHandlerType(protocolId); AppDomainProtocolHandler handler = null; LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); lock (ac) { HostingEnvironmentParameters hostingParameters = new HostingEnvironmentParameters(); hostingParameters.HostingFlags = HostingEnvironmentFlags.ThrowHostingInitErrors; PreloadApplicationIfRequired(appId, appHost, hostingParameters, ac); // call app manager to create the handler handler = (AppDomainProtocolHandler)_appManager.CreateObjectInternal( appId, handlerType, appHost, false /*failIfExists*/, hostingParameters); // create a shim object that we can use for proxy unwrapping ListenerAdapterDispatchShim shim = (ListenerAdapterDispatchShim) _appManager.CreateObjectInternal( appId, typeof(ListenerAdapterDispatchShim), appHost, false /*failIfExists*/, hostingParameters); if (null != shim) { shim.StartListenerChannel(handler, listenerChannelCallback); // remove the shim ((IRegisteredObject)shim).Stop(true); } else { throw new HttpException(SR.GetString(SR.Failure_Create_Listener_Shim)); } } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Start_AppDomain_Listener)} ); } throw; } } public void StopAppDomainProtocolListenerChannel(String appId, String protocolId, int listenerChannelId, bool immediate) { try { if (appId == null) throw new ArgumentNullException("appId"); if (protocolId == null) throw new ArgumentNullException("protocolId"); // get app domaoin protocol handler type from config Type handlerType = GetAppDomainProtocolHandlerType(protocolId); AppDomainProtocolHandler handler = null; LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); lock (ac) { // call app manager to create the handler handler = (AppDomainProtocolHandler)_appManager.GetObject(appId, handlerType); } // stop the listenerChannel if (handler != null) { handler.StopListenerChannel(listenerChannelId, immediate); } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Stop_AppDomain_Listener)} ); } throw; } } public void StopAppDomainProtocol(String appId, String protocolId, bool immediate) { try { if (appId == null) throw new ArgumentNullException("appId"); if (protocolId == null) throw new ArgumentNullException("protocolId"); // get app domaoin protocol handler type from config Type handlerType = GetAppDomainProtocolHandlerType(protocolId); AppDomainProtocolHandler handler = null; LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); lock (ac) { // call app manager to create the handler handler = (AppDomainProtocolHandler)_appManager.GetObject(appId, handlerType); } // stop protocol if (handler != null) { handler.StopProtocol(immediate); } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Stop_AppDomain_Protocol)} ); } throw; } } public void StartApplication(String appId, String appPath, out Object runtimeInterface) { try { if (appId == null) throw new ArgumentNullException("appId"); if (appPath == null) throw new ArgumentNullException("appPath"); Debug.Assert(_functions != null, "_functions != null"); runtimeInterface = null; PipelineRuntime runtime = null; // // Fill app a Dictionary with 'binding rules' -- name value string pairs // for app domain creation // // if (appPath[0] == '.') { System.IO.FileInfo file = new System.IO.FileInfo(appPath); appPath = file.FullName; } if (!StringUtil.StringEndsWith(appPath, '\\')) { appPath = appPath + "\\"; } // Create new app host of a consistent type IApplicationHost appHost = CreateAppHost(appId, appPath); // // Create the AppDomain and a registered object in it // LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); lock (ac) { // #1 WOS 1690249: ASP.Net v2.0: ASP.NET stress: 2nd chance exception: Attempted to access an unloaded AppDomain. // if an old AppDomain exists with a PipelineRuntime, remove it from // AppManager._appDomains so that a new AppDomain will be created // #2 WOS 1977425: ASP.NET apps continue recycling after touching machine.config once - this used to initiate shutdown, // but that can cause us to recycle the app repeatedly if we initiate shutdown before IIS initiates shutdown of the // previous app. _appManager.RemoveFromTableIfRuntimeExists(appId, typeof(PipelineRuntime)); // Preload (if required) the App Domain before letting the first request to be processed PreloadApplicationIfRequired(appId, appHost, null, ac); try { runtime = (PipelineRuntime)_appManager.CreateObjectInternal( appId, typeof(PipelineRuntime), appHost, true /* failIfExists */, null /* default */ ); } catch (AppDomainUnloadedException) { // munch it so we can retry again } if (null != runtime) { runtime.SetThisAppDomainsIsapiAppId(appId); runtime.StartProcessing(); runtimeInterface = new ObjectHandle(runtime); } } } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Start_Integrated_App)} ); } throw; } } public void ShutdownApplication(String appId) { try { // call into app manager _appManager.ShutdownApplication(appId); } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Stop_Integrated_App)} ); } throw; } } public void Shutdown() { try { // collect all protocols under lock ArrayList protocolList = new ArrayList(); int refCount = 0; lock (this) { // lookup protocol handler foreach (DictionaryEntry e in _protocolHandlers) { protocolList.Add(e.Value); } _protocolHandlers = new Hashtable(); } // stop all process protocols outside of lock foreach (ProcessProtocolHandler p in protocolList) { p.StopProtocol(true); } // call into app manager to shutdown _appManager.ShutdownAll(); // SupportFunctions interface provided by native layer // must be released now. // Otherwise the release of the COM object will have // to wait for GC. Native layer assumes that after // returning from Shutdown there is no reference // to the native objects from ProcessHost. // do { refCount = Marshal.ReleaseComObject( _functions ); } while( refCount != 0 ); } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_Shutdown_ProcessHost), e.ToString()} ); } throw; } } public void EnumerateAppDomains( out IAppDomainInfoEnum appDomainInfoEnum ) { try { ApplicationManager appManager = ApplicationManager.GetApplicationManager(); AppDomainInfo [] infos; infos = appManager.GetAppDomainInfos(); appDomainInfoEnum = new AppDomainInfoEnum(infos); } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_AppDomain_Enum)} ); } throw; } } // IProcessHostIdleAndHealthCheck interface implementation public bool IsIdle() { bool result = false; try { result = _appManager.IsIdle(); } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_PMH_Idle)} ); } throw; } return result; } public void Ping(IProcessPingCallback callback) { try { if (callback != null) _appManager.Ping(callback); } catch (Exception e) { using (new ProcessImpersonationContext()) { Misc.ReportUnhandledException(e, new string[] { SR.GetString(SR.Failure_PMH_Ping)} ); } throw; } } private ISAPIApplicationHost CreateAppHost(string appId, string appPath) { // // if we have a null physical path, we need // to use the PMH to resolve it // if (String.IsNullOrEmpty(appPath)) { string virtualPath; string physicalPath; string siteName; string siteID; _functions.GetApplicationProperties( appId, out virtualPath, out physicalPath, out siteName, out siteID); // // make sure physical app path ends with '\\' and virtual does not // if (!StringUtil.StringEndsWith(physicalPath, '\\')) { physicalPath = physicalPath + "\\"; } Debug.Assert( !String.IsNullOrEmpty(physicalPath), "!String.IsNullOrEmpty(physicalPath)"); appPath = physicalPath; } // // Create a new application host // This needs to be a coherent type across all // protocol types so that we get a consistent // environment regardless of which protocol initializes first // ISAPIApplicationHost appHost = new ISAPIApplicationHost( appId, appPath, false, /* validatePhysicalPath */ _functions ); return appHost; } public void SetApplicationPreloadUtil(IApplicationPreloadUtil applicationPreloadUtil) { // Do not allow setting PreloadUtil again if it has already has been set if (_preloadUtil != null) { throw new InvalidOperationException(SR.GetString(SR.Failure_ApplicationPreloadUtil_Already_Set)); } _preloadUtil = applicationPreloadUtil; } public void SetApplicationPreloadState(string context, string appId, bool enabled) { // Check params if (String.IsNullOrEmpty(context)) { throw ExceptionUtil.ParameterNullOrEmpty("context"); } if (String.IsNullOrEmpty(appId)) { throw ExceptionUtil.ParameterNullOrEmpty("appId"); } // _preloadUtil must be not null if we have an application preload enabled if (enabled && _preloadUtil == null) { throw new ArgumentException(SR.GetString(SR.Invalid_Enabled_Preload_Parameter), "enabled"); } LockableAppDomainContext ac = _appManager.GetLockableAppDomainContext(appId); lock (ac) { ac.PreloadContext = context; if (enabled) { PreloadApplicationIfRequired(appId, null, null, ac); } } } internal static void PreloadApplicationIfNotShuttingdown (string appId, LockableAppDomainContext ac) { if (ProcessHost.DefaultHost != null && UnsafeIISMethods.MgdHasConfigChanged()) { // Start the new app on another thread instead of hijacking the current app unloading thread ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o) { lock (ac) { try { // NOTE: we don't know what HostingEnvironmentParameters were passed to our previous application instance // so we pass null (default for HTTP activation). We could have cached it in ApplicationContext if needed ProcessHost.DefaultHost.PreloadApplicationIfRequired(appId, null, null, ac); } catch (Exception e) { ProcessHost.DefaultHost.ReportApplicationPreloadFailureWithAssert( ac.PreloadContext, HResults.E_FAIL, Misc.FormatExceptionMessage( e, new string[] { SR.GetString(SR.Failure_Preload_Application_Initialization)})); } } })); } } // New for Dev10. // creates a new AppDomain, preloads and calls user code in it internal void PreloadApplicationIfRequired( string appId, IApplicationHost appHostParameter, HostingEnvironmentParameters hostingParameters, LockableAppDomainContext ac) { // NOTE1: Must never be called under lock (_appManager) // NOTE2: Must always be called under lock (ac) // We only need to preload if auto start is enabled and we have not already preloaded (i.e. HostingEnvironment doesn't exist) if (_preloadUtil == null || ac.PreloadContext == null || ac.HostEnv != null) { return; } // Get and verify the preload parameters string preloadObjTypeName; string[] paramsForStartupObj; bool stillEnabled; GetApplicationPreloadInfoWithAssert(ac.PreloadContext, out stillEnabled, out preloadObjTypeName, out paramsForStartupObj); // Dev10: 782385 ASP.NET autostart implementation should be tolerant of empty string for the provider type if (!stillEnabled || String.IsNullOrEmpty(preloadObjTypeName)) { return; } // Ready to load the App Domain if (_preloadingThrottle != null) { // Throttle the number of simultaneously created appdomains _preloadingThrottle.WaitOne(); } try { // Create the app-host and start a new App Domain IApplicationHost appHost = (appHostParameter == null) ? CreateAppHost(appId, null) : appHostParameter; // call app manager to create the PreloadHost PreloadHost preloadHostObj = (PreloadHost)_appManager.CreateObjectInternal( appId, typeof(PreloadHost), appHost, true /*failIfExists*/, hostingParameters); // Dev10 858421: File sharing violations on config files cause unnecessary process shutdown in autostart mode // // There are race conditions between whoever modifies the config files // and the application config system that reads from the config files // These file sharing violation lead to random application initialization failures // Service auto-start mode is more vulnerable to these sharing violations because // it starts a new app domain as soon as the file change notification is received // and when an error occurs IIS recycles the whole app pool rather than a particular app // // In most cases that we see in stress the inner most exception is System.IO.IOException // so if we see this exception we will give it another try before // reporting the errors to IIS and recycling the process // // Check for I/O exceptions during initialization and retry one time Exception appInitEx = preloadHostObj.InitializationException; if (GetInnerMostException(appInitEx) is IOException) { try { // prevent ApplicationManager.HostingEnvironmentShutdownInitiated from attempting to preload again ac.RetryingPreload = true; // shutdown old hosting environment ac.HostEnv.InitiateShutdownInternal(); } finally { ac.RetryingPreload = false; } // Create the app-host and start a new App Domain appHost = (appHostParameter == null) ? CreateAppHost(appId, null) : appHostParameter; // call app manager to create the PreloadHost preloadHostObj = (PreloadHost)_appManager.CreateObjectInternal( appId, typeof(PreloadHost), appHost, true /*failIfExists*/, hostingParameters); appInitEx = preloadHostObj.InitializationException; } // Check again for initialization exception and tell IIS to recycle the process if (appInitEx != null) { ReportApplicationPreloadFailureWithAssert( ac.PreloadContext, HResults.E_FAIL, Misc.FormatExceptionMessage( appInitEx, new string[] { SR.GetString(SR.Failure_Preload_Application_Initialization)} )); // we must throw if preload fails because we cannot allow the normal // startup path to continue and attempt to create a HostingEnvironment throw appInitEx; } // Call preload code in the App Domain try { preloadHostObj.CreateIProcessHostPreloadClientInstanceAndCallPreload(preloadObjTypeName, paramsForStartupObj); } catch (Exception e) { // report errors ReportApplicationPreloadFailureWithAssert( ac.PreloadContext, HResults.E_FAIL, Misc.FormatExceptionMessage( e, new string[] { SR.GetString(SR.Failure_Calling_Preload_Provider)} ).ToString()); throw; } } finally { if (_preloadingThrottle != null) { _preloadingThrottle.Release(); } } } private static Exception GetInnerMostException(Exception e) { if (e == null) { return null; } while (e.InnerException != null) { e = e.InnerException; } return e; } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] private void GetApplicationPreloadInfoWithAssert( string context, out bool enabled, out string startupObjType, out string[] parametersForStartupObj) { _preloadUtil.GetApplicationPreloadInfo(context, out enabled, out startupObjType, out parametersForStartupObj); } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] private void ReportApplicationPreloadFailureWithAssert(string context, int errorCode, string errorMessage) { _preloadUtil.ReportApplicationPreloadFailure(context, errorCode, errorMessage); } } internal sealed class ListenerAdapterDispatchShim : MarshalByRefObject, IRegisteredObject { void IRegisteredObject.Stop(bool immediate) { HostingEnvironment.UnregisterObject(this); } // this should run in an Hosted app domain (not in the default domain) internal void StartListenerChannel( AppDomainProtocolHandler handler, IListenerChannelCallback listenerCallback ) { Debug.Assert( HostingEnvironment.IsHosted, "HostingEnvironment.IsHosted" ); Debug.Assert( null != handler, "null != handler" ); IListenerChannelCallback unwrappedProxy = MarshalComProxy(listenerCallback); Debug.Assert(null != unwrappedProxy, "null != unwrappedProxy"); if (null != unwrappedProxy && null != handler) { handler.StartListenerChannel(unwrappedProxy); } } internal IListenerChannelCallback MarshalComProxy(IListenerChannelCallback defaultDomainCallback) { IListenerChannelCallback localProxy = null; // get the underlying COM object IntPtr pUnk = Marshal.GetIUnknownForObject(defaultDomainCallback); // this object isn't a COM object if (IntPtr.Zero == pUnk) { return null; } IntPtr ppv = IntPtr.Zero; try { // QI it for the interface Guid g = typeof(IListenerChannelCallback).GUID; int hresult = Marshal.QueryInterface(pUnk, ref g, out ppv); if (hresult < 0) { Marshal.ThrowExceptionForHR(hresult); } // create a RCW we can hold onto in this domain // this bumps the ref count so we can drop our refs on the raw interfaces localProxy = (IListenerChannelCallback)Marshal.GetObjectForIUnknown(ppv); } finally { // drop our explicit refs and keep the managed instance if (IntPtr.Zero != ppv) { Marshal.Release(ppv); } if (IntPtr.Zero != pUnk) { Marshal.Release(pUnk); } } return localProxy; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AnnotationMap.cs
- MimeBasePart.cs
- DataException.cs
- InfoCardRSAPKCS1SignatureDeformatter.cs
- ConfigurationPropertyCollection.cs
- GeneralTransform3DGroup.cs
- ListViewInsertionMark.cs
- Hex.cs
- Error.cs
- ImageBrush.cs
- Brush.cs
- Matrix3DValueSerializer.cs
- BodyGlyph.cs
- ContentPosition.cs
- FontUnitConverter.cs
- SqlVersion.cs
- SimpleHandlerBuildProvider.cs
- SelectionItemProviderWrapper.cs
- SerializationException.cs
- AppSettingsSection.cs
- DocumentPageViewAutomationPeer.cs
- FixedSchema.cs
- CodeAssignStatement.cs
- Activator.cs
- HtmlElementCollection.cs
- WebConvert.cs
- MatrixTransform3D.cs
- WindowsFormsLinkLabel.cs
- Fx.cs
- MultipartIdentifier.cs
- CodeTypeReference.cs
- OutOfProcStateClientManager.cs
- Timer.cs
- DependencyStoreSurrogate.cs
- HttpContext.cs
- StateMachineAction.cs
- ChannelDispatcherBase.cs
- ClientTarget.cs
- OutputCacheModule.cs
- WebPartAuthorizationEventArgs.cs
- WorkflowOwnershipException.cs
- DataKey.cs
- StrongName.cs
- SamlAssertion.cs
- PassportAuthenticationModule.cs
- SortDescription.cs
- ItemsPanelTemplate.cs
- XPathDocumentBuilder.cs
- StylusDownEventArgs.cs
- HierarchicalDataTemplate.cs
- ConnectionsZone.cs
- TypeCodeDomSerializer.cs
- AppDomain.cs
- WizardStepBase.cs
- ResourceDescriptionAttribute.cs
- ValidatedMobileControlConverter.cs
- InternalTypeHelper.cs
- Serializer.cs
- QilGenerator.cs
- PropertyValueChangedEvent.cs
- XmlSchemaChoice.cs
- ExitEventArgs.cs
- Cast.cs
- AspProxy.cs
- HtmlInputRadioButton.cs
- Line.cs
- _CookieModule.cs
- ComboBoxAutomationPeer.cs
- HistoryEventArgs.cs
- ListControlStringCollectionEditor.cs
- IIS7WorkerRequest.cs
- CompositeFontInfo.cs
- UriExt.cs
- DataGridViewTextBoxCell.cs
- Substitution.cs
- ImageMapEventArgs.cs
- ToolStripProfessionalLowResolutionRenderer.cs
- X509UI.cs
- MenuCommand.cs
- Vector3DCollectionValueSerializer.cs
- HttpApplicationFactory.cs
- LockingPersistenceProvider.cs
- BinHexEncoder.cs
- RectangleGeometry.cs
- EncryptedReference.cs
- TreeView.cs
- DataGridViewCellStyle.cs
- ParameterRetriever.cs
- DataKey.cs
- DataGridViewRowStateChangedEventArgs.cs
- PropertyCollection.cs
- BindingCollection.cs
- PointCollection.cs
- BitmapEffectDrawingContent.cs
- GridEntry.cs
- ToolBarButton.cs
- StylusOverProperty.cs
- HighContrastHelper.cs
- StylusButtonCollection.cs
- FormatVersion.cs