Fix EBUSY errors on uv_loop_close (#1798)
* Fix race where ListenerPrimary is disposed before secondary listeners spin up - Since we only add listeners to dispatch pipes after receiving the "ack" message it's possible to have pipes that were created but not acked yet. We might miss disposal of those pipes if they were never added to the list of _dispatchPipes. #1761
This commit is contained in:
parent
4dd4a573e6
commit
35b5d92652
|
|
@ -264,6 +264,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
_post.Reference();
|
||||
_post.Dispose();
|
||||
|
||||
// We need this walk because we call ReadStop on on accepted connections when there's back pressure
|
||||
// Calling ReadStop makes the handle as in-active which means the loop can
|
||||
// end while there's still valid handles around. This makes loop.Dispose throw
|
||||
// with an EBUSY. To avoid that, we walk all of the handles and dispose them.
|
||||
Walk(ptr =>
|
||||
{
|
||||
var handle = UvMemory.FromIntPtr<UvHandle>(ptr);
|
||||
// handle can be null because UvMemory.FromIntPtr looks up a weak reference
|
||||
handle?.Dispose();
|
||||
});
|
||||
|
||||
// Ensure the Dispose operations complete in the event loop.
|
||||
_loop.Run();
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
/// </summary>
|
||||
public class ListenerPrimary : Listener
|
||||
{
|
||||
// The list of pipes that can be dispatched to (where we've confirmed the _pipeMessage)
|
||||
private readonly List<UvPipeHandle> _dispatchPipes = new List<UvPipeHandle>();
|
||||
// The list of pipes we've created but may not be part of _dispatchPipes
|
||||
private readonly List<UvPipeHandle> _createdPipes = new List<UvPipeHandle>();
|
||||
private int _dispatchIndex;
|
||||
private string _pipeName;
|
||||
private byte[] _pipeMessage;
|
||||
|
|
@ -78,6 +81,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
}
|
||||
|
||||
var dispatchPipe = new UvPipeHandle(Log);
|
||||
// Add to the list of created pipes for disposal tracking
|
||||
_createdPipes.Add(dispatchPipe);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -191,9 +196,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
{
|
||||
listener.ListenPipe.Dispose();
|
||||
|
||||
foreach (var dispatchPipe in listener._dispatchPipes)
|
||||
foreach (var pipe in listener._createdPipes)
|
||||
{
|
||||
dispatchPipe.Dispose();
|
||||
pipe.Dispose();
|
||||
}
|
||||
}, this).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue