Merge branch 'benaadams/listenersecondary-allocs' into dev
This commit is contained in:
commit
74f08c16df
|
|
@ -17,8 +17,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ListenerSecondary : ListenerContext, IDisposable
|
public abstract class ListenerSecondary : ListenerContext, IDisposable
|
||||||
{
|
{
|
||||||
|
private string _pipeName;
|
||||||
|
private IntPtr _ptr;
|
||||||
|
private Libuv.uv_buf_t _buf;
|
||||||
|
|
||||||
protected ListenerSecondary(ServiceContext serviceContext) : base(serviceContext)
|
protected ListenerSecondary(ServiceContext serviceContext) : base(serviceContext)
|
||||||
{
|
{
|
||||||
|
_ptr = Marshal.AllocHGlobal(4);
|
||||||
|
_buf = Thread.Loop.Libuv.buf_init(_ptr, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
UvPipeHandle DispatchPipe { get; set; }
|
UvPipeHandle DispatchPipe { get; set; }
|
||||||
|
|
@ -29,97 +35,116 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
KestrelThread thread,
|
KestrelThread thread,
|
||||||
RequestDelegate application)
|
RequestDelegate application)
|
||||||
{
|
{
|
||||||
|
_pipeName = pipeName;
|
||||||
ServerAddress = address;
|
ServerAddress = address;
|
||||||
Thread = thread;
|
Thread = thread;
|
||||||
Application = application;
|
Application = application;
|
||||||
|
|
||||||
DispatchPipe = new UvPipeHandle(Log);
|
DispatchPipe = new UvPipeHandle(Log);
|
||||||
|
|
||||||
var tcs = new TaskCompletionSource<int>();
|
var tcs = new TaskCompletionSource<int>(this);
|
||||||
Thread.Post(_ =>
|
Thread.Post(tcs2 => StartCallback(tcs2), tcs);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DispatchPipe.Init(Thread.Loop, true);
|
|
||||||
var connect = new UvConnectRequest(Log);
|
|
||||||
connect.Init(Thread.Loop);
|
|
||||||
connect.Connect(
|
|
||||||
DispatchPipe,
|
|
||||||
pipeName,
|
|
||||||
(connect2, status, error, state) =>
|
|
||||||
{
|
|
||||||
connect.Dispose();
|
|
||||||
if (error != null)
|
|
||||||
{
|
|
||||||
tcs.SetException(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ptr = Marshal.AllocHGlobal(4);
|
|
||||||
var buf = Thread.Loop.Libuv.buf_init(ptr, 4);
|
|
||||||
|
|
||||||
DispatchPipe.ReadStart(
|
|
||||||
(_1, _2, _3) => buf,
|
|
||||||
(_1, status2, state2) =>
|
|
||||||
{
|
|
||||||
if (status2 < 0)
|
|
||||||
{
|
|
||||||
if (status2 != Constants.EOF)
|
|
||||||
{
|
|
||||||
Exception ex;
|
|
||||||
Thread.Loop.Libuv.Check(status2, out ex);
|
|
||||||
Log.LogError("DispatchPipe.ReadStart", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchPipe.Dispose();
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DispatchPipe.PendingCount() == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var acceptSocket = CreateAcceptSocket();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DispatchPipe.Accept(acceptSocket);
|
|
||||||
}
|
|
||||||
catch (UvException ex)
|
|
||||||
{
|
|
||||||
Log.LogError("DispatchPipe.Accept", ex);
|
|
||||||
acceptSocket.Dispose();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var connection = new Connection(this, acceptSocket);
|
|
||||||
connection.Start();
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
|
|
||||||
tcs.SetResult(0);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
DispatchPipe.Dispose();
|
|
||||||
tcs.SetException(ex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
DispatchPipe.Dispose();
|
|
||||||
tcs.SetException(ex);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void StartCallback(TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
var listener = (ListenerSecondary)tcs.Task.AsyncState;
|
||||||
|
listener.StartedCallback(tcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartedCallback(TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DispatchPipe.Init(Thread.Loop, true);
|
||||||
|
var connect = new UvConnectRequest(Log);
|
||||||
|
connect.Init(Thread.Loop);
|
||||||
|
connect.Connect(
|
||||||
|
DispatchPipe,
|
||||||
|
_pipeName,
|
||||||
|
(connect2, status, error, state) => ConnectCallback(connect2, status, error, (TaskCompletionSource<int>)state),
|
||||||
|
tcs);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
DispatchPipe.Dispose();
|
||||||
|
tcs.SetException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConnectCallback(UvConnectRequest connect, int status, Exception error, TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
var listener = (ListenerSecondary)tcs.Task.AsyncState;
|
||||||
|
listener.ConnectedCallback(connect, status, error, tcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConnectedCallback(UvConnectRequest connect, int status, Exception error, TaskCompletionSource<int> tcs)
|
||||||
|
{
|
||||||
|
connect.Dispose();
|
||||||
|
if (error != null)
|
||||||
|
{
|
||||||
|
tcs.SetException(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DispatchPipe.ReadStart(
|
||||||
|
(handle, status2, state) => ((ListenerSecondary)state)._buf,
|
||||||
|
(handle, status2, state) =>
|
||||||
|
{
|
||||||
|
var listener = ((ListenerSecondary)state);
|
||||||
|
listener.ReadStartCallback(handle, status2, listener._ptr);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
tcs.SetResult(0);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
DispatchPipe.Dispose();
|
||||||
|
tcs.SetException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadStartCallback(UvStreamHandle handle, int status, IntPtr ptr)
|
||||||
|
{
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
if (status != Constants.EOF)
|
||||||
|
{
|
||||||
|
Exception ex;
|
||||||
|
Thread.Loop.Libuv.Check(status, out ex);
|
||||||
|
Log.LogError("DispatchPipe.ReadStart", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchPipe.Dispose();
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DispatchPipe.PendingCount() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var acceptSocket = CreateAcceptSocket();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DispatchPipe.Accept(acceptSocket);
|
||||||
|
}
|
||||||
|
catch (UvException ex)
|
||||||
|
{
|
||||||
|
Log.LogError("DispatchPipe.Accept", ex);
|
||||||
|
acceptSocket.Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var connection = new Connection(this, acceptSocket);
|
||||||
|
connection.Start();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a socket which can be used to accept an incoming connection
|
/// Creates a socket which can be used to accept an incoming connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -127,13 +152,15 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
Marshal.FreeHGlobal(_ptr);
|
||||||
|
|
||||||
// Ensure the event loop is still running.
|
// Ensure the event loop is still running.
|
||||||
// If the event loop isn't running and we try to wait on this Post
|
// If the event loop isn't running and we try to wait on this Post
|
||||||
// to complete, then KestrelEngine will never be disposed and
|
// to complete, then KestrelEngine will never be disposed and
|
||||||
// the exception that stopped the event loop will never be surfaced.
|
// the exception that stopped the event loop will never be surfaced.
|
||||||
if (Thread.FatalError == null)
|
if (Thread.FatalError == null)
|
||||||
{
|
{
|
||||||
Thread.Send(_ => DispatchPipe.Dispose(), null);
|
Thread.Send(listener => ((ListenerSecondary)listener).DispatchPipe.Dispose(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue