HostFactoryResolver - Increase default timeout to thirty seconds (#61621)
authorMaryam Ariyan <maryam.ariyan@microsoft.com>
Wed, 17 Nov 2021 19:09:08 +0000 (11:09 -0800)
committerGitHub <noreply@github.com>
Wed, 17 Nov 2021 19:09:08 +0000 (14:09 -0500)
src/libraries/Microsoft.Extensions.HostFactoryResolver/src/HostFactoryResolver.cs
src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs
src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj
src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/Program.cs [new file with mode: 0644]
src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj [new file with mode: 0644]

index d860312..ec4335d 100644 (file)
@@ -20,9 +20,25 @@ namespace Microsoft.Extensions.Hosting
         public const string BuildWebHost = nameof(BuildWebHost);
         public const string CreateWebHostBuilder = nameof(CreateWebHostBuilder);
         public const string CreateHostBuilder = nameof(CreateHostBuilder);
+        private const string TimeoutEnvironmentKey = "DOTNET_HOST_FACTORY_RESOLVER_DEFAULT_TIMEOUT_IN_SECONDS";
 
         // The amount of time we wait for the diagnostic source events to fire
-        private static readonly TimeSpan s_defaultWaitTimeout = Debugger.IsAttached ? Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(5);
+        private static readonly TimeSpan s_defaultWaitTimeout = SetupDefaultTimout();
+
+        private static TimeSpan SetupDefaultTimout()
+        {
+            if (Debugger.IsAttached)
+            {
+                return Timeout.InfiniteTimeSpan;
+            }
+            
+            if (uint.TryParse(Environment.GetEnvironmentVariable(TimeoutEnvironmentKey), out uint timeoutInSeconds))
+            {
+                return TimeSpan.FromSeconds((int)timeoutInSeconds);
+            }
+
+            return TimeSpan.FromMinutes(5);
+        }
 
         public static Func<string[], TWebHost>? ResolveWebHostFactory<TWebHost>(Assembly assembly)
         {
@@ -229,7 +245,7 @@ namespace Microsoft.Extensions.Hosting
 
                         // Try to set an exception if the entry point returns gracefully, this will force
                         // build to throw
-                        _hostTcs.TrySetException(new InvalidOperationException("Unable to build IHost"));
+                        _hostTcs.TrySetException(new InvalidOperationException("The entry point exited without ever building an IHost."));
                     }
                     catch (TargetInvocationException tie) when (tie.InnerException is StopTheHostException)
                     {
@@ -268,7 +284,7 @@ namespace Microsoft.Extensions.Hosting
                     // Wait before throwing an exception
                     if (!_hostTcs.Task.Wait(_waitTimeout))
                     {
-                        throw new InvalidOperationException("Unable to build IHost");
+                        throw new InvalidOperationException($"Timed out waiting for the entry point to build the IHost after {s_defaultWaitTimeout}. This timeout can be modified using the '{TimeoutEnvironmentKey}' environment variable.");
                     }
                 }
                 catch (AggregateException) when (_hostTcs.Task.IsCompleted)
index 0e353f7..d6cf530 100644 (file)
@@ -254,6 +254,16 @@ namespace Microsoft.Extensions.Hosting.Tests
         }
 
         [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
+        public void TopLevelStatementsTestsTimeout()
+        {
+            var assembly = Assembly.Load("TopLevelStatementsTestsTimeout");
+            var factory = HostFactoryResolver.ResolveServiceProviderFactory(assembly, s_WaitTimeout);
+
+            Assert.NotNull(factory);
+            Assert.Throws<InvalidOperationException>(() => factory(Array.Empty<string>()));
+        }
+
+        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
         public void ApplicationNameSetFromAgrument()
         {
             Assembly assembly = Assembly.Load("ApplicationNameSetFromAgrument");
index 795e830..61edd76 100644 (file)
@@ -28,6 +28,7 @@
     <ProjectReference Include="NoSpecialEntryPointPatternHangs\NoSpecialEntryPointPatternHangs.csproj" />
     <ProjectReference Include="NoSpecialEntryPointPatternMainNoArgs\NoSpecialEntryPointPatternMainNoArgs.csproj" />
     <ProjectReference Include="TopLevelStatements\TopLevelStatements.csproj" />
+    <ProjectReference Include="TopLevelStatementsTestsTimeout\TopLevelStatementsTestsTimeout.csproj" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/Program.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/Program.cs
new file mode 100644 (file)
index 0000000..f4c0188
--- /dev/null
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Threading;
+using Microsoft.Extensions.Hosting;
+
+var hostBuilder = new HostBuilder();
+Thread.Sleep(TimeSpan.FromSeconds(30));
+hostBuilder.Build();
\ No newline at end of file
diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj
new file mode 100644 (file)
index 0000000..1d8d76f
--- /dev/null
@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
+    <EnableDefaultItems>true</EnableDefaultItems>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\MockHostTypes\MockHostTypes.csproj" />
+  </ItemGroup>
+
+</Project>