Better handle OnHeartbeat in 32-bit environments
- Prevent potential overflow when casting a long to an IntPtr
This commit is contained in:
parent
89a63d190e
commit
c4762cdfd5
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -25,8 +26,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
private static readonly Action<object, object> _postAsyncCallbackAdapter = (callback, state) => ((Action<object>)callback).Invoke(state);
|
||||
private static readonly Libuv.uv_walk_cb _heartbeatWalkCallback = (ptr, arg) =>
|
||||
{
|
||||
var handle = UvMemory.FromIntPtr<UvHandle>(ptr);
|
||||
(handle as UvStreamHandle)?.Connection?.Tick((long)arg);
|
||||
var streamHandle = UvMemory.FromIntPtr<UvHandle>(ptr) as UvStreamHandle;
|
||||
var thisHandle = GCHandle.FromIntPtr(arg);
|
||||
var kestrelThread = (KestrelThread)thisHandle.Target;
|
||||
streamHandle?.Connection?.Tick(kestrelThread.Now);
|
||||
};
|
||||
|
||||
// maximum times the work queues swapped and are processed in a single pass
|
||||
|
|
@ -53,6 +56,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
private readonly IKestrelTrace _log;
|
||||
private readonly IThreadPool _threadPool;
|
||||
private readonly TimeSpan _shutdownTimeout;
|
||||
private IntPtr _thisPtr;
|
||||
|
||||
public KestrelThread(KestrelEngine engine)
|
||||
{
|
||||
|
|
@ -99,6 +103,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
|
||||
private Action<Action<IntPtr>, IntPtr> QueueCloseAsyncHandle { get; }
|
||||
|
||||
// The cached result of Loop.Now() which is a timestamp in milliseconds
|
||||
private long Now { get; set; }
|
||||
|
||||
public Task StartAsync()
|
||||
{
|
||||
var tcs = new TaskCompletionSource<int>();
|
||||
|
|
@ -303,8 +310,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
}
|
||||
}
|
||||
|
||||
// This is used to access a 64-bit timestamp (this.Now) using a potentially 32-bit IntPtr.
|
||||
var thisHandle = GCHandle.Alloc(this, GCHandleType.Weak);
|
||||
|
||||
try
|
||||
{
|
||||
_thisPtr = GCHandle.ToIntPtr(thisHandle);
|
||||
|
||||
_loop.Run();
|
||||
if (_stopImmediate)
|
||||
{
|
||||
|
|
@ -331,6 +343,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
}
|
||||
finally
|
||||
{
|
||||
thisHandle.Free();
|
||||
_threadTcs.SetResult(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -349,7 +362,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
|
||||
private void OnHeartbeat(UvTimerHandle timer)
|
||||
{
|
||||
Walk(_heartbeatWalkCallback, (IntPtr)Loop.Now());
|
||||
Now = Loop.Now();
|
||||
Walk(_heartbeatWalkCallback, _thisPtr);
|
||||
}
|
||||
|
||||
private bool DoPostWork()
|
||||
|
|
|
|||
Loading…
Reference in New Issue