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)
{
// 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)
{
// 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)
}
[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");
--- /dev/null
+// 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