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

Commit b755818

Browse files
committed
#302 Add a timeout for draining requests on shutdown
1 parent baf311c commit b755818

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ internal class MessagePump : IServer
2929
private bool _stopping;
3030
private int _outstandingRequests;
3131
private ManualResetEvent _shutdownSignal;
32+
private TimeSpan _shutdownTimeout;
3233

3334
private readonly ServerAddressesFeature _serverAddresses;
3435

@@ -54,6 +55,7 @@ public MessagePump(IOptions<WebListenerOptions> options, ILoggerFactory loggerFa
5455
_maxAccepts = optionsInstance.MaxAccepts;
5556
EnableResponseCaching = optionsInstance.EnableResponseCaching;
5657
_shutdownSignal = new ManualResetEvent(false);
58+
_shutdownTimeout = TimeSpan.FromSeconds(5);
5759
}
5860

5961
internal Microsoft.Net.Http.Server.WebListener Listener
@@ -222,7 +224,15 @@ public void Dispose()
222224
if (_outstandingRequests > 0)
223225
{
224226
LogHelper.LogInfo(_logger, "Stopping, waiting for " + _outstandingRequests + " request(s) to drain.");
225-
_shutdownSignal.WaitOne();
227+
var drained = _shutdownSignal.WaitOne(_shutdownTimeout);
228+
if (drained)
229+
{
230+
LogHelper.LogInfo(_logger, "All requests drained successfully.");
231+
}
232+
else
233+
{
234+
LogHelper.LogInfo(_logger, "Timed out, terminating " + _outstandingRequests + " request(s).");
235+
}
226236
}
227237
// All requests are finished
228238
_listener.Dispose();

test/Microsoft.AspNetCore.Server.WebListener.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
[Fact]
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+
[Fact]
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
[Fact]
91115
public void Server_AppException_ClientReset()
92116
{

0 commit comments

Comments
 (0)