Fix deadlocks in startup and shutdown
This commit is contained in:
parent
ed4a27a827
commit
6036f27f52
|
|
@ -287,7 +287,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
|||
var connectionHandler = new ConnectionHandler<TContext>(ipv4ListenOptions, serviceContext, application);
|
||||
var transport = _transportFactory.Create(ipv4ListenOptions, connectionHandler);
|
||||
_transports.Add(transport);
|
||||
await transport.BindAsync();
|
||||
await transport.BindAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (AddressInUseException ex)
|
||||
{
|
||||
|
|
@ -306,7 +306,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
|
|||
var connectionHandler = new ConnectionHandler<TContext>(ipv6ListenOptions, serviceContext, application);
|
||||
var transport = _transportFactory.Create(ipv6ListenOptions, connectionHandler);
|
||||
_transports.Add(transport);
|
||||
await transport.BindAsync();
|
||||
await transport.BindAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (AddressInUseException ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
private readonly UvStreamHandle _socket;
|
||||
private IConnectionContext _connectionContext;
|
||||
|
||||
private TaskCompletionSource<object> _socketClosedTcs = new TaskCompletionSource<object>();
|
||||
private TaskCompletionSource<object> _socketClosedTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
private WritableBuffer? _currentWritableBuffer;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
private async Task<bool> WalkConnectionsAsync(Action<LibuvConnectionManager, TaskCompletionSource<object>> action, TimeSpan timeout)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
_thread.Post(state => action(state, tcs), this);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
private readonly LibuvTransport _transport;
|
||||
private readonly IApplicationLifetime _appLifetime;
|
||||
private readonly Thread _thread;
|
||||
private readonly TaskCompletionSource<object> _threadTcs = new TaskCompletionSource<object>();
|
||||
private readonly TaskCompletionSource<object> _threadTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
private readonly UvLoopHandle _loop;
|
||||
private readonly UvAsyncHandle _post;
|
||||
private Queue<Work> _workAdding = new Queue<Work>(1024);
|
||||
|
|
@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
public Task StartAsync()
|
||||
{
|
||||
var tcs = new TaskCompletionSource<int>();
|
||||
var tcs = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
_thread.Start(tcs);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
public Task PostAsync<T>(Action<T> callback, T state)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
lock (_workSync)
|
||||
{
|
||||
_workAdding.Enqueue(new Work
|
||||
|
|
@ -332,36 +332,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
try
|
||||
{
|
||||
work.CallbackAdapter(work.Callback, work.State);
|
||||
if (work.Completion != null)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
{
|
||||
try
|
||||
{
|
||||
((TaskCompletionSource<object>)o).SetResult(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(0, e, $"{nameof(LibuvThread)}.{nameof(DoPostWork)}");
|
||||
}
|
||||
}, work.Completion);
|
||||
}
|
||||
work.Completion?.TrySetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (work.Completion != null)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(o =>
|
||||
{
|
||||
try
|
||||
{
|
||||
((TaskCompletionSource<object>)o).TrySetException(ex);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.LogError(0, e, $"{nameof(LibuvThread)}.{nameof(DoPostWork)}");
|
||||
}
|
||||
}, work.Completion);
|
||||
work.Completion.TrySetException(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,25 +31,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
EndPointInformation = endPointInformation;
|
||||
Thread = thread;
|
||||
|
||||
var tcs = new TaskCompletionSource<int>(this);
|
||||
|
||||
Thread.Post(state =>
|
||||
return Thread.PostAsync(listener =>
|
||||
{
|
||||
var tcs2 = state;
|
||||
try
|
||||
{
|
||||
var listener = ((Listener) tcs2.Task.AsyncState);
|
||||
listener.ListenSocket = listener.CreateListenSocket();
|
||||
ListenSocket.Listen(LibuvConstants.ListenBacklog, ConnectionCallback, this);
|
||||
tcs2.SetResult(0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs2.SetException(ex);
|
||||
}
|
||||
}, tcs);
|
||||
|
||||
return tcs.Task;
|
||||
listener.ListenSocket = listener.CreateListenSocket();
|
||||
listener.ListenSocket.Listen(LibuvConstants.ListenBacklog, ConnectionCallback, listener);
|
||||
}, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -157,9 +143,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
// the exception that stopped the event loop will never be surfaced.
|
||||
if (Thread.FatalError == null && ListenSocket != null)
|
||||
{
|
||||
await Thread.PostAsync(state =>
|
||||
await Thread.PostAsync(listener =>
|
||||
{
|
||||
var listener = (Listener)state;
|
||||
listener.ListenSocket.Dispose();
|
||||
|
||||
listener._closed = true;
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
await StartAsync(endPointInformation, thread).ConfigureAwait(false);
|
||||
|
||||
await Thread.PostAsync(state => ((ListenerPrimary)state).PostCallback(),
|
||||
this).ConfigureAwait(false);
|
||||
await Thread.PostAsync(listener => listener.PostCallback(), this).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private void PostCallback()
|
||||
|
|
@ -175,9 +174,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
|
||||
if (Thread.FatalError == null && ListenPipe != null)
|
||||
{
|
||||
await Thread.PostAsync(state =>
|
||||
await Thread.PostAsync(listener =>
|
||||
{
|
||||
var listener = (ListenerPrimary)state;
|
||||
listener.ListenPipe.Dispose();
|
||||
|
||||
foreach (var dispatchPipe in listener._dispatchPipes)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
Thread = thread;
|
||||
DispatchPipe = new UvPipeHandle(Log);
|
||||
|
||||
var tcs = new TaskCompletionSource<int>(this);
|
||||
var tcs = new TaskCompletionSource<int>(this, TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
Thread.Post(StartCallback, tcs);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
|
@ -185,9 +185,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
|
|||
// the exception that stopped the event loop will never be surfaced.
|
||||
if (Thread.FatalError == null)
|
||||
{
|
||||
await Thread.PostAsync(state =>
|
||||
await Thread.PostAsync(listener =>
|
||||
{
|
||||
var listener = (ListenerSecondary)state;
|
||||
listener.DispatchPipe.Dispose();
|
||||
listener.FreeBuffer();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue