Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit cb55973

Browse files
authored
Dispose the host if Initialize fails (#1318)
1 parent ad2fd9e commit cb55973

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public IWebHostBuilder ConfigureServices(Action<IServiceCollection> configureSer
100100
throw new ArgumentNullException(nameof(configureServices));
101101
}
102102

103-
return ConfigureServices((_ , services) => configureServices(services));
103+
return ConfigureServices((_, services) => configureServices(services));
104104
}
105105

106106
/// <summary>
@@ -189,10 +189,19 @@ public IWebHost Build()
189189
_options,
190190
_config,
191191
hostingStartupErrors);
192+
try
193+
{
194+
host.Initialize();
192195

193-
host.Initialize();
194-
195-
return host;
196+
return host;
197+
}
198+
catch
199+
{
200+
// Dispose the host if there's a failure to initialize, this should clean up
201+
// will dispose services that were constructed until the exception was thrown
202+
host.Dispose();
203+
throw;
204+
}
196205
}
197206

198207
private IServiceCollection BuildCommonServices(out AggregateException hostingStartupErrors)

test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,23 @@ public void DoNotCaptureStartupErrorsByDefault()
369369
Assert.Equal("A public method named 'ConfigureProduction' or 'Configure' could not be found in the 'Microsoft.AspNetCore.Hosting.Fakes.StartupBoom' type.", exception.Message);
370370
}
371371

372+
[Fact]
373+
public void ServiceProviderDisposedOnBuildException()
374+
{
375+
var service = new DisposableService();
376+
var hostBuilder = new WebHostBuilder()
377+
.UseServer(new TestServer())
378+
.ConfigureServices(services =>
379+
{
380+
// Added as a factory since instances are never disposed by the container
381+
services.AddSingleton(sp => service);
382+
})
383+
.UseStartup<StartupWithResolvedDisposableThatThrows>();
384+
385+
Assert.Throws<InvalidOperationException>(() => hostBuilder.Build());
386+
Assert.True(service.Disposed);
387+
}
388+
372389
[Fact]
373390
public void CaptureStartupErrorsHonored()
374391
{
@@ -1050,6 +1067,16 @@ public void Configure(IApplicationBuilder app)
10501067
}
10511068
}
10521069

1070+
public class DisposableService : IDisposable
1071+
{
1072+
public bool Disposed { get; private set; }
1073+
1074+
public void Dispose()
1075+
{
1076+
Disposed = true;
1077+
}
1078+
}
1079+
10531080
public class TestHostingStartup : IHostingStartup
10541081
{
10551082
public void Configure(IWebHostBuilder builder)
@@ -1068,6 +1095,24 @@ public void Configure(IWebHostBuilder builder)
10681095
}
10691096
}
10701097

1098+
public class StartupWithResolvedDisposableThatThrows
1099+
{
1100+
public StartupWithResolvedDisposableThatThrows(DisposableService service)
1101+
{
1102+
1103+
}
1104+
1105+
public void ConfigureServices(IServiceCollection services)
1106+
{
1107+
throw new InvalidOperationException();
1108+
}
1109+
1110+
public void Configure(IApplicationBuilder app)
1111+
{
1112+
1113+
}
1114+
}
1115+
10711116
public class TestLoggerProvider : ILoggerProvider
10721117
{
10731118
public TestSink Sink { get; set; } = new TestSink();

0 commit comments

Comments
 (0)