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

Commit 83837a9

Browse files
committed
#301 Add a timeout for draining requests on shutdown
1 parent a3ac694 commit 83837a9

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
@@ -69,7 +69,7 @@ public async Task Server_EchoHelloWorld_Success()
6969
}
7070

7171
[ConditionalFact]
72-
public async Task Server_ShutdownDurringRequest_Success()
72+
public async Task Server_ShutdownDuringRequest_Success()
7373
{
7474
Task<string> responseTask;
7575
ManualResetEvent received = new ManualResetEvent(false);
@@ -88,6 +88,30 @@ public async Task Server_ShutdownDurringRequest_Success()
8888
Assert.Equal("Hello World", response);
8989
}
9090

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

0 commit comments

Comments
 (0)