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
- DataProtection.cs
- SaveWorkflowCommand.cs
- TemplateInstanceAttribute.cs
- Column.cs
- WSTrustFeb2005.cs
- WsiProfilesElement.cs
- IPGlobalProperties.cs
- ValueChangedEventManager.cs
- PolyQuadraticBezierSegmentFigureLogic.cs
- CodePageEncoding.cs
- DecodeHelper.cs
- DataGridColumnCollectionEditor.cs
- CompilerGeneratedAttribute.cs
- CatchDesigner.xaml.cs
- CreateSequenceResponse.cs
- ContextMarshalException.cs
- DownloadProgressEventArgs.cs
- AffineTransform3D.cs
- HostVisual.cs
- RichTextBoxConstants.cs
- ProtocolsInstallComponent.cs
- StringResourceManager.cs
- TextSerializer.cs
- MemoryMappedViewAccessor.cs
- UserControl.cs
- Assert.cs
- basecomparevalidator.cs
- XmlLoader.cs
- RemoteWebConfigurationHostStream.cs
- Int32KeyFrameCollection.cs
- HtmlAnchor.cs
- TextRangeBase.cs
- XmlTextReaderImplHelpers.cs
- ImageMapEventArgs.cs
- WindowsPen.cs
- TypeName.cs
- ListenerConnectionModeReader.cs
- PersonalizationEntry.cs
- SchemaElementLookUpTable.cs
- StyleSelector.cs
- IsolatedStorageFilePermission.cs
- TableDetailsCollection.cs
- TextSearch.cs
- UndoEngine.cs
- FormViewUpdateEventArgs.cs
- AttributeCollection.cs
- EventLogWatcher.cs
- DataBoundControl.cs
- DataGridColumnHeader.cs
- DependentList.cs
- ClientSideProviderDescription.cs
- DataGridViewColumnDividerDoubleClickEventArgs.cs
- List.cs
- Partitioner.cs
- HttpCachePolicy.cs
- InfiniteIntConverter.cs
- XsltCompileContext.cs
- PackageFilter.cs
- pingexception.cs
- SqlLiftIndependentRowExpressions.cs
- XamlBrushSerializer.cs
- StreamAsIStream.cs
- GeometryHitTestParameters.cs
- WindowsSecurityToken.cs
- DesignerTransaction.cs
- WorkflowTraceTransfer.cs
- SiteMapSection.cs
- URL.cs
- WebRequest.cs
- WebContext.cs
- ServiceOperationUIEditor.cs
- Size3DValueSerializer.cs
- FontCollection.cs
- Rect.cs
- WsatServiceCertificate.cs
- DebugView.cs
- SystemColors.cs
- SHA1CryptoServiceProvider.cs
- MulticastOption.cs
- errorpatternmatcher.cs
- CategoryGridEntry.cs
- DataGridViewIntLinkedList.cs
- ControlBuilderAttribute.cs
- OpenFileDialog.cs
- AttachedPropertyBrowsableWhenAttributePresentAttribute.cs
- BulletedListEventArgs.cs
- DataViewListener.cs
- FastPropertyAccessor.cs
- HelpKeywordAttribute.cs
- DispatcherHookEventArgs.cs
- TaskCanceledException.cs
- StatusBarItem.cs
- propertyentry.cs
- SqlDataSourceCache.cs
- PrivilegeNotHeldException.cs
- BordersPage.cs
- ObfuscationAttribute.cs
- InlineObject.cs
- SystemUnicastIPAddressInformation.cs
- CollectionEditorDialog.cs