Fixed the bug in the windows service host where if application stop is requested, the service wouldn't know about it. (#4553)
* Fixed the bug in the windows service host where if application stop is requested, the service wouldn't know about it. * Fixed a typo. * Update src/Hosting/WindowsServices/test/Microsoft.AspNetCore.Hosting.WindowsServices.Tests.csproj * Removed unneeded EditorBrowsable for internal API. * Fixed tests to ignore Linux and MacOS. * Added new line to end of file. * Using [ConditionalFact] instead of [Fact].
This commit is contained in:
parent
3f4622ffe0
commit
c560edee28
|
|
@ -25,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.TestHo
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.WindowsServices", "WindowsServices\src\Microsoft.AspNetCore.Hosting.WindowsServices.csproj", "{FA29445B-1BA7-448D-8ADF-56BF6D6633BB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Hosting.WindowsServices.Tests", "WindowsServices\test\Microsoft.AspNetCore.Hosting.WindowsServices.Tests.csproj", "{CCD5D010-7E06-4209-ADD5-3B010A41DCF1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{31587D24-F6B5-4A47-A962-47CA7FEA79D0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildWebHostInvalidSignature", "test\testassets\BuildWebHostInvalidSignature\BuildWebHostInvalidSignature.csproj", "{BF146375-AA6C-43F3-BF0A-DCA551892DF8}"
|
||||
|
|
@ -89,6 +91,10 @@ Global
|
|||
{FA29445B-1BA7-448D-8ADF-56BF6D6633BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FA29445B-1BA7-448D-8ADF-56BF6D6633BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FA29445B-1BA7-448D-8ADF-56BF6D6633BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CCD5D010-7E06-4209-ADD5-3B010A41DCF1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BF146375-AA6C-43F3-BF0A-DCA551892DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Hosting.WindowsServices.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ServiceProcess;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
|
|
@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Hosting.WindowsServices
|
|||
/// </summary>
|
||||
public class WebHostService : ServiceBase
|
||||
{
|
||||
private IWebHost _host;
|
||||
private readonly IWebHost _host;
|
||||
private bool _stopRequestedByWindows;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -24,14 +25,27 @@ namespace Microsoft.AspNetCore.Hosting.WindowsServices
|
|||
_host = host ?? throw new ArgumentNullException(nameof(host));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is not intended for direct use. Its sole purpose is to allow
|
||||
/// the service to be started by the tests.
|
||||
/// </summary>
|
||||
internal void Start() => OnStart(Array.Empty<string>());
|
||||
|
||||
protected sealed override void OnStart(string[] args)
|
||||
{
|
||||
OnStarting(args);
|
||||
|
||||
_host.Start();
|
||||
|
||||
OnStarted();
|
||||
|
||||
// Register callback for application stopping after we've
|
||||
// started the service, because otherwise we might introduce unwanted
|
||||
// race conditions.
|
||||
_host
|
||||
.Services
|
||||
.GetRequiredService<IApplicationLifetime>()
|
||||
.ApplicationStopped
|
||||
.ApplicationStopping
|
||||
.Register(() =>
|
||||
{
|
||||
if (!_stopRequestedByWindows)
|
||||
|
|
@ -39,10 +53,6 @@ namespace Microsoft.AspNetCore.Hosting.WindowsServices
|
|||
Stop();
|
||||
}
|
||||
});
|
||||
|
||||
_host.Start();
|
||||
|
||||
OnStarted();
|
||||
}
|
||||
|
||||
protected sealed override void OnStop()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Hosting" />
|
||||
<Reference Include="Microsoft.AspNetCore.Hosting.WindowsServices" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
[assembly: OSSkipCondition(OperatingSystems.MacOSX)]
|
||||
[assembly: OSSkipCondition(OperatingSystems.Linux)]
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.ServiceProcess;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Hosting.WindowsServices;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Hosting
|
||||
{
|
||||
public class WebHostServiceTests
|
||||
{
|
||||
// Reasonable timeout for our test operations to complete.
|
||||
private static readonly TimeSpan OperationTimeout = TimeSpan.FromSeconds( 5 );
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task StopBeforeServiceStarted()
|
||||
{
|
||||
var host = new WebHostBuilder().UseServer(new FakeServer()).Configure(x => { }).Build();
|
||||
var webHostService = new WebHostService(host);
|
||||
var applicationLifetime = host.Services.GetRequiredService<IApplicationLifetime>();
|
||||
|
||||
applicationLifetime.StopApplication();
|
||||
webHostService.Start();
|
||||
|
||||
await Assert.ThrowsAsync<TaskCanceledException>(
|
||||
() => Task.Delay(OperationTimeout, applicationLifetime.ApplicationStopped));
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task StopAfterServiceStarted()
|
||||
{
|
||||
var host = new WebHostBuilder().UseServer( new FakeServer() ).Configure( x => { } ).Build();
|
||||
var webHostService = new WebHostService(host);
|
||||
var applicationLifetime = host.Services.GetRequiredService<IApplicationLifetime>();
|
||||
|
||||
webHostService.Start();
|
||||
applicationLifetime.StopApplication();
|
||||
|
||||
await Assert.ThrowsAsync<TaskCanceledException>(
|
||||
() => Task.Delay(OperationTimeout, applicationLifetime.ApplicationStopped));
|
||||
}
|
||||
|
||||
private sealed class FakeServer : IServer
|
||||
{
|
||||
IFeatureCollection IServer.Features { get; }
|
||||
public RequestDelegate RequestDelegate { get; private set; }
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken)
|
||||
{
|
||||
RequestDelegate = ctx => throw new NotSupportedException();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue