Using weak gchandles from native to managed

See #15
This commit is contained in:
Louis DeJardin 2014-07-08 14:51:13 -07:00
parent ca9e837048
commit 836be5565a
4 changed files with 30 additions and 10 deletions

View File

@ -95,8 +95,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
else if (normalDone || errorDone) else if (normalDone || errorDone)
{ {
KestrelTrace.Log.ConnectionReadFin(_connectionId); KestrelTrace.Log.ConnectionReadFin(_connectionId);
SocketInput.RemoteIntakeFin = true; SocketInput.RemoteIntakeFin = true;
_socket.ReadStop();
if (errorDone && error != null) if (errorDone && error != null)
{ {

View File

@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Server.Kestrel
{ {
foreach (var thread in Threads) foreach (var thread in Threads)
{ {
thread.Stop(TimeSpan.FromSeconds(45)); thread.Stop(TimeSpan.FromSeconds(2.5));
} }
Threads.Clear(); Threads.Clear();
} }

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
_threadId = Thread.CurrentThread.ManagedThreadId; _threadId = Thread.CurrentThread.ManagedThreadId;
handle = Marshal.AllocCoTaskMem(size); handle = Marshal.AllocCoTaskMem(size);
*(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this)); *(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Weak));
} }
protected void CreateHandle(UvLoopHandle loop, int size) protected void CreateHandle(UvLoopHandle loop, int size)
@ -54,7 +54,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
{ {
Trace.Assert(closed || !IsClosed, "Handle is closed"); Trace.Assert(closed || !IsClosed, "Handle is closed");
Trace.Assert(!IsInvalid, "Handle is invalid"); Trace.Assert(!IsInvalid, "Handle is invalid");
Trace.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is correct"); Trace.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is incorrect");
} }
unsafe protected static void DestroyHandle(IntPtr memory) unsafe protected static void DestroyHandle(IntPtr memory)

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Server.Kestrel.Networking namespace Microsoft.AspNet.Server.Kestrel.Networking
{ {
@ -12,19 +13,33 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
private readonly static Libuv.uv_alloc_cb _uv_alloc_cb = UvAllocCb; private readonly static Libuv.uv_alloc_cb _uv_alloc_cb = UvAllocCb;
private readonly static Libuv.uv_read_cb _uv_read_cb = UvReadCb; private readonly static Libuv.uv_read_cb _uv_read_cb = UvReadCb;
public Action<UvStreamHandle, int, Exception, object> _connectionCallback; public Action<UvStreamHandle, int, Exception, object> _listenCallback;
public object _connectionState; public object _listenState;
private GCHandle _listenVitality;
public Func<UvStreamHandle, int, object, Libuv.uv_buf_t> _allocCallback; public Func<UvStreamHandle, int, object, Libuv.uv_buf_t> _allocCallback;
public Action<UvStreamHandle, int, Exception, object> _readCallback; public Action<UvStreamHandle, int, Exception, object> _readCallback;
public object _readState; public object _readState;
private GCHandle _readVitality;
protected override bool ReleaseHandle()
{
if (_listenVitality.IsAllocated)
{
_listenVitality.Free();
}
if (_readVitality.IsAllocated)
{
_readVitality.Free();
}
return base.ReleaseHandle();
}
public void Listen(int backlog, Action<UvStreamHandle, int, Exception, object> callback, object state) public void Listen(int backlog, Action<UvStreamHandle, int, Exception, object> callback, object state)
{ {
_connectionCallback = callback; _listenCallback = callback;
_connectionState = state; _listenState = state;
_listenVitality = GCHandle.Alloc(this, GCHandleType.Normal);
_uv.listen(this, 10, _uv_connection_cb); _uv.listen(this, 10, _uv_connection_cb);
} }
@ -41,11 +56,16 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
_allocCallback = allocCallback; _allocCallback = allocCallback;
_readCallback = readCallback; _readCallback = readCallback;
_readState = state; _readState = state;
_readVitality = GCHandle.Alloc(this, GCHandleType.Normal);
_uv.read_start(this, _uv_alloc_cb, _uv_read_cb); _uv.read_start(this, _uv_alloc_cb, _uv_read_cb);
} }
public void ReadStop() public void ReadStop()
{ {
_allocCallback = null;
_readCallback = null;
_readState = null;
_readVitality.Free();
_uv.read_stop(this); _uv.read_stop(this);
} }
@ -64,7 +84,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Networking
try try
{ {
stream._connectionCallback(stream, status, error, stream._connectionState); stream._listenCallback(stream, status, error, stream._listenState);
} }
catch (Exception ex) catch (Exception ex)
{ {