Skip to content

Commit f52cb2c

Browse files
committed
feedback and add another shutdown test file
1 parent c433c09 commit f52cb2c

File tree

4 files changed

+71
-57
lines changed

4 files changed

+71
-57
lines changed

src/Servers/IIS/IIS/src/Core/IISHttpServer.cs

+3-17
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ internal class IISHttpServer : IServer
2525
private static readonly NativeMethods.PFN_SHUTDOWN_HANDLER _shutdownHandler = HandleShutdown;
2626
private static readonly NativeMethods.PFN_DISCONNECT_HANDLER _onDisconnect = OnDisconnect;
2727
private static readonly NativeMethods.PFN_ASYNC_COMPLETION _onAsyncCompletion = OnAsyncCompletion;
28-
private static readonly NativeMethods.PFN_REQUESTS_DRAINED_HANDLER _drainHandler = OnRequestsDrained;
28+
private static readonly NativeMethods.PFN_REQUESTS_DRAINED_HANDLER _requestsDrainedHandler = OnRequestsDrained;
2929

3030
private IISContextFactory _iisContextFactory;
3131
private readonly MemoryPool<byte> _memoryPool = new SlabMemoryPool();
@@ -36,8 +36,6 @@ internal class IISHttpServer : IServer
3636
private readonly IISNativeApplication _nativeApplication;
3737
private readonly ServerAddressesFeature _serverAddressesFeature;
3838

39-
private CancellationTokenRegistration _stopRegistration;
40-
4139
private readonly TaskCompletionSource<object> _shutdownSignal = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
4240
private bool? _websocketAvailable;
4341

@@ -88,7 +86,7 @@ public Task StartAsync<TContext>(IHttpApplication<TContext> application, Cancell
8886
_httpServerHandle = GCHandle.Alloc(this);
8987

9088
_iisContextFactory = new IISContextFactory<TContext>(_memoryPool, application, _options, this, _logger);
91-
_nativeApplication.RegisterCallbacks(_requestHandler, _shutdownHandler, _onDisconnect, _onAsyncCompletion, _drainHandler, (IntPtr)_httpServerHandle, (IntPtr)_httpServerHandle);
89+
_nativeApplication.RegisterCallbacks(_requestHandler, _shutdownHandler, _onDisconnect, _onAsyncCompletion, _requestsDrainedHandler, (IntPtr)_httpServerHandle, (IntPtr)_httpServerHandle);
9290

9391
_serverAddressesFeature.Addresses = _options.ServerAddresses;
9492

@@ -99,18 +97,6 @@ public Task StopAsync(CancellationToken cancellationToken)
9997
{
10098
_nativeApplication.StopIncomingRequests();
10199

102-
try
103-
{
104-
_stopRegistration = cancellationToken.Register(() =>
105-
{
106-
_shutdownSignal.TrySetResult(null);
107-
});
108-
}
109-
catch (Exception ex)
110-
{
111-
_shutdownSignal.TrySetException(ex);
112-
}
113-
114100
return _shutdownSignal.Task;
115101
}
116102

@@ -206,13 +192,13 @@ private static void OnRequestsDrained(IntPtr serverContext)
206192

207193
server._nativeApplication.StopCallsIntoManaged();
208194
server._shutdownSignal.TrySetResult(null);
209-
server._stopRegistration.Dispose();
210195
}
211196
catch (Exception ex)
212197
{
213198
server?._logger.LogError(0, ex, $"Unexpected exception in {nameof(IISHttpServer)}.{nameof(OnRequestsDrained)}.");
214199
}
215200
}
201+
216202
private class IISContextFactory<T> : IISContextFactory
217203
{
218204
private readonly IHttpApplication<T> _application;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
// Copyright (c) .NET Foundation. All rights reserved.
3+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
4+
5+
using System.IO;
6+
using System.Net.Http;
7+
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
9+
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
10+
using Microsoft.AspNetCore.Testing.xunit;
11+
using Xunit;
12+
13+
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
14+
{
15+
[Collection(PublishedSitesCollection.Name)]
16+
public class IISExpressShutdownTests : IISFunctionalTestBase
17+
{
18+
private readonly PublishedSitesFixture _fixture;
19+
20+
public IISExpressShutdownTests(PublishedSitesFixture fixture)
21+
{
22+
_fixture = fixture;
23+
}
24+
25+
[ConditionalFact]
26+
public async Task ShutdownTimeoutIsApplied()
27+
{
28+
var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true);
29+
deploymentParameters.TransformArguments((a, _) => $"{a} HangOnStop");
30+
deploymentParameters.WebConfigActionList.Add(
31+
WebConfigHelpers.AddOrModifyAspNetCoreSection("shutdownTimeLimit", "1"));
32+
33+
var deploymentResult = await DeployAsync(deploymentParameters);
34+
35+
Assert.Equal("Hello World", await deploymentResult.HttpClient.GetStringAsync("/HelloWorld"));
36+
37+
StopServer();
38+
39+
EventLogHelpers.VerifyEventLogEvents(deploymentResult,
40+
EventLogHelpers.InProcessStarted(deploymentResult),
41+
EventLogHelpers.InProcessFailedToStop(deploymentResult, ""));
42+
}
43+
44+
[ConditionalTheory]
45+
[InlineData("/ShutdownStopAsync")]
46+
[InlineData("/ShutdownStopAsyncWithCancelledToken")]
47+
public async Task CallStopAsyncOnRequestThread_DoesNotHangIndefinitely(string path)
48+
{
49+
// Canceled token doesn't affect shutdown, in-proc doesn't handle ungraceful shutdown
50+
// IIS's ShutdownTimeLimit will handle that.
51+
var parameters = _fixture.GetBaseDeploymentParameters(publish: true);
52+
var deploymentResult = await DeployAsync(parameters);
53+
try
54+
{
55+
await deploymentResult.HttpClient.GetAsync(path);
56+
}
57+
catch (HttpRequestException ex) when (ex.InnerException is IOException)
58+
{
59+
// Server might close a connection before request completes
60+
}
61+
62+
deploymentResult.AssertWorkerProcessStop();
63+
}
64+
}
65+
}

src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs

+1-19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Linq;
88
using System.Net;
9+
using System.Net.Http;
910
using System.Text.RegularExpressions;
1011
using System.Threading.Tasks;
1112
using System.Xml.Linq;
@@ -340,25 +341,6 @@ public async Task StartupTimeoutIsApplied()
340341
);
341342
}
342343

343-
[ConditionalFact]
344-
public async Task ShutdownTimeoutIsApplied()
345-
{
346-
var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true);
347-
deploymentParameters.TransformArguments((a, _) => $"{a} HangOnStop");
348-
deploymentParameters.WebConfigActionList.Add(
349-
WebConfigHelpers.AddOrModifyAspNetCoreSection("shutdownTimeLimit", "1"));
350-
351-
var deploymentResult = await DeployAsync(deploymentParameters);
352-
353-
Assert.Equal("Hello World", await deploymentResult.HttpClient.GetStringAsync("/HelloWorld"));
354-
355-
StopServer();
356-
357-
EventLogHelpers.VerifyEventLogEvents(deploymentResult,
358-
EventLogHelpers.InProcessStarted(deploymentResult),
359-
EventLogHelpers.InProcessFailedToStop(deploymentResult, ""));
360-
}
361-
362344
[ConditionalFact]
363345
public async Task CheckInvalidHostingModelParameter()
364346
{

src/Servers/IIS/IIS/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs renamed to src/Servers/IIS/IIS/test/IISExpress.FunctionalTests/InProcess/IISExpressShutdownTests.cs

+2-21
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
1616
{
1717
[Collection(PublishedSitesCollection.Name)]
18-
public class ShutdownTests : IISFunctionalTestBase
18+
public class IISExpressShutdownTests : IISFunctionalTestBase
1919
{
2020
private readonly PublishedSitesFixture _fixture;
2121

22-
public ShutdownTests(PublishedSitesFixture fixture)
22+
public IISExpressShutdownTests(PublishedSitesFixture fixture)
2323
{
2424
_fixture = fixture;
2525
}
@@ -87,24 +87,5 @@ public async Task ForcefulShutdown_DoesCrashProcess()
8787
StopServer(gracefulShutdown: false);
8888
Assert.True(result.HostProcess.ExitCode == 1);
8989
}
90-
91-
[ConditionalTheory]
92-
[InlineData("/ShutdownStopAsync")]
93-
[InlineData("/ShutdownStopAsyncWithCancelledToken")]
94-
public async Task CallStopAsyncOnRequestThread_DoesNotHangIndefinitely(string path)
95-
{
96-
var parameters = _fixture.GetBaseDeploymentParameters(publish: true);
97-
var deploymentResult = await DeployAsync(parameters);
98-
try
99-
{
100-
await deploymentResult.HttpClient.GetAsync(path);
101-
}
102-
catch (HttpRequestException ex) when (ex.InnerException is IOException)
103-
{
104-
// Server might close a connection before request completes
105-
}
106-
107-
deploymentResult.AssertWorkerProcessStop();
108-
}
10990
}
11091
}

0 commit comments

Comments
 (0)