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

Commit 56bd85a

Browse files
committed
#298 Add a timeout for draining requests on shutdown
1 parent e19dea2 commit 56bd85a

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

src/Microsoft.AspNetCore.Server.HttpSys/HttpSysOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ public long RequestQueueLimit
8181
}
8282
}
8383

84+
/// <summary>
85+
/// The amount of time to wait for active requests to drain while the server is shutting down.
86+
/// New requests will receive a 503 response in this time period. The default is 5 seconds.
87+
/// </summary>
88+
public TimeSpan ShutdownTimeout { get; set; } = TimeSpan.FromSeconds(5);
89+
8490
internal void SetRequestQueueLimit(RequestQueue requestQueue)
8591
{
8692
_requestQueue = requestQueue;

src/Microsoft.AspNetCore.Server.HttpSys/MessagePump.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,15 @@ public void Dispose()
221221
if (_outstandingRequests > 0)
222222
{
223223
LogHelper.LogInfo(_logger, "Stopping, waiting for " + _outstandingRequests + " request(s) to drain.");
224-
_shutdownSignal.WaitOne();
224+
var drained = _shutdownSignal.WaitOne(Listener.Options.ShutdownTimeout);
225+
if (drained)
226+
{
227+
LogHelper.LogInfo(_logger, "All requests drained successfully.");
228+
}
229+
else
230+
{
231+
LogHelper.LogInfo(_logger, "Timed out, terminating " + _outstandingRequests + " request(s).");
232+
}
225233
}
226234
// All requests are finished
227235
_listener.Dispose();

test/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests/ServerTests.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public async Task Server_EchoHelloWorld_Success()
6868
}
6969

7070
[ConditionalFact]
71-
public async Task Server_ShutdownDurringRequest_Success()
71+
public async Task Server_ShutdownDuringRequest_Success()
7272
{
7373
Task<string> responseTask;
7474
ManualResetEvent received = new ManualResetEvent(false);
@@ -87,6 +87,30 @@ public async Task Server_ShutdownDurringRequest_Success()
8787
Assert.Equal("Hello World", response);
8888
}
8989

90+
[ConditionalFact]
91+
public async Task Server_ShutdownDuringLongRunningRequest_TimesOut()
92+
{
93+
Task<string> responseTask;
94+
var received = new ManualResetEvent(false);
95+
bool? shutdown = null;
96+
var waitForShutdown = new ManualResetEvent(false);
97+
string address;
98+
using (Utilities.CreateHttpServer(out address, httpContext =>
99+
{
100+
received.Set();
101+
shutdown = waitForShutdown.WaitOne(TimeSpan.FromSeconds(15));
102+
httpContext.Response.ContentLength = 11;
103+
return httpContext.Response.WriteAsync("Hello World");
104+
}))
105+
{
106+
responseTask = SendRequestAsync(address);
107+
Assert.True(received.WaitOne(TimeSpan.FromSeconds(10)));
108+
}
109+
Assert.False(shutdown.HasValue);
110+
waitForShutdown.Set();
111+
await Assert.ThrowsAsync<HttpRequestException>(async () => await responseTask);
112+
}
113+
90114
[ConditionalFact]
91115
public void Server_AppException_ClientReset()
92116
{

0 commit comments

Comments
 (0)