Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit 55d997b

Browse files
committed
Fixed shutdown hanging
- Added Stopping event to KestrelThread so that incoming connections get a chance to gracefully close before disposing the event loop - Call _post.Dispose instead of UnReference. Sometimes Dispose would happen on the finalizer thread and _queueCloseHandle would be null. #9
1 parent e421b3f commit 55d997b

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public Connection(ListenerContext context, UvStreamHandle socket) : base(context
6161
{
6262
_socket = socket;
6363
ConnectionControl = this;
64+
65+
Thread.OnStopping += OnLoopStopping;
6466
}
6567

6668
public void Start()
@@ -73,6 +75,11 @@ public void Start()
7375
_socket.ReadStart(_allocCallback, _readCallback, this);
7476
}
7577

78+
private void OnLoopStopping()
79+
{
80+
_socket.Dispose();
81+
}
82+
7683
private Libuv.uv_buf_t OnAlloc(UvStreamHandle handle, int suggestedSize)
7784
{
7885
return handle.Libuv.buf_init(

src/Microsoft.AspNet.Server.Kestrel/Infrastructure/KestrelThread.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class KestrelThread
2626
Queue<CloseHandle> _closeHandleRunning = new Queue<CloseHandle>();
2727
object _workSync = new Object();
2828
bool _stopImmediate = false;
29+
volatile bool _aborting = false;
2930
private ExceptionDispatchInfo _closeError;
3031

3132
public KestrelThread(KestrelEngine engine)
@@ -41,6 +42,8 @@ public KestrelThread(KestrelEngine engine)
4142

4243
public Action<Action<IntPtr>, IntPtr> QueueCloseHandle { get; internal set; }
4344

45+
public event Action OnStopping;
46+
4447
public Task StartAsync()
4548
{
4649
var tcs = new TaskCompletionSource<int>();
@@ -61,6 +64,7 @@ public void Stop(TimeSpan timeout)
6164
#endif
6265
}
6366
}
67+
6468
if (_closeError != null)
6569
{
6670
_closeError.Throw();
@@ -69,7 +73,13 @@ public void Stop(TimeSpan timeout)
6973

7074
private void OnStop(object obj)
7175
{
72-
_post.Unreference();
76+
if (OnStopping != null)
77+
{
78+
OnStopping();
79+
}
80+
81+
_aborting = true;
82+
_post.Dispose();
7383
}
7484

7585
private void OnStopImmediate(object obj)
@@ -80,6 +90,11 @@ private void OnStopImmediate(object obj)
8090

8191
public void Post(Action<object> callback, object state)
8292
{
93+
if (_aborting)
94+
{
95+
return;
96+
}
97+
8398
lock (_workSync)
8499
{
85100
_workAdding.Enqueue(new Work { Callback = callback, State = state });
@@ -130,19 +145,6 @@ private void ThreadStart(object parameter)
130145
return;
131146
}
132147

133-
// run the loop one more time to delete the open handles
134-
_post.Reference();
135-
_post.DangerousClose();
136-
_engine.Libuv.walk(
137-
_loop,
138-
(ptr, arg) =>
139-
{
140-
var handle = UvMemory.FromIntPtr<UvHandle>(ptr);
141-
handle.Dispose();
142-
},
143-
IntPtr.Zero);
144-
var ran2 = _loop.Run();
145-
146148
_loop.Dispose();
147149
}
148150
catch (Exception ex)

0 commit comments

Comments
 (0)