Gracefully shutdown even when there are open connections

This commit is contained in:
Stephen Halter 2015-06-11 16:56:33 -07:00
parent 2bc5d9518b
commit b43e5940e5
4 changed files with 30 additions and 13 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ _ReSharper.*/
packages/ packages/
artifacts/ artifacts/
PublishProfiles/ PublishProfiles/
.vs/
*.user *.user
*.suo *.suo
*.cache *.cache

View File

@ -53,12 +53,16 @@ namespace Microsoft.AspNet.Server.Kestrel
Post(OnStop, null); Post(OnStop, null);
if (!_thread.Join((int)timeout.TotalMilliseconds)) if (!_thread.Join((int)timeout.TotalMilliseconds))
{ {
Post(OnStopImmediate, null); Post(OnStopRude, null);
if (!_thread.Join((int)timeout.TotalMilliseconds)) if (!_thread.Join((int)timeout.TotalMilliseconds))
{ {
Post(OnStopImmediate, null);
if (!_thread.Join((int)timeout.TotalMilliseconds))
{
#if DNX451 #if DNX451
_thread.Abort(); _thread.Abort();
#endif #endif
}
} }
} }
if (_closeError != null) if (_closeError != null)
@ -72,6 +76,21 @@ namespace Microsoft.AspNet.Server.Kestrel
_post.Unreference(); _post.Unreference();
} }
private void OnStopRude(object obj)
{
_engine.Libuv.walk(
_loop,
(ptr, arg) =>
{
var handle = UvMemory.FromIntPtr<UvHandle>(ptr);
if (handle != _post)
{
handle.Dispose();
}
},
IntPtr.Zero);
}
private void OnStopImmediate(object obj) private void OnStopImmediate(object obj)
{ {
_stopImmediate = true; _stopImmediate = true;
@ -133,14 +152,8 @@ namespace Microsoft.AspNet.Server.Kestrel
// run the loop one more time to delete the open handles // run the loop one more time to delete the open handles
_post.Reference(); _post.Reference();
_post.DangerousClose(); _post.DangerousClose();
_engine.Libuv.walk(
_loop, // Ensure the "DangerousClose" operation completes in the event loop.
(ptr, arg) =>
{
var handle = UvMemory.FromIntPtr<UvHandle>(ptr);
handle.Dispose();
},
IntPtr.Zero);
var ran2 = _loop.Run(); var ran2 = _loop.Run();
_loop.Dispose(); _loop.Dispose();
@ -203,7 +216,7 @@ namespace Microsoft.AspNet.Server.Kestrel
queue = _closeHandleAdding; queue = _closeHandleAdding;
_closeHandleAdding = _closeHandleRunning; _closeHandleAdding = _closeHandleRunning;
_closeHandleRunning = queue; _closeHandleRunning = queue;
} }
while (queue.Count != 0) while (queue.Count != 0)
{ {
var closeHandle = queue.Dequeue(); var closeHandle = queue.Dequeue();

View File

@ -32,9 +32,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
{ {
_uv.close(memory, _destroyMemory); _uv.close(memory, _destroyMemory);
} }
else else if (_queueCloseHandle != null)
{ {
_queueCloseHandle(memory2 => _uv.close(memory2, _destroyMemory), memory); // This can be called from the finalizer.
// Ensure the closure doesn't reference "this".
var uv = _uv;
_queueCloseHandle(memory2 => uv.close(memory2, _destroyMemory), memory);
} }
} }
return true; return true;