parent
0ac478858d
commit
6a403d231e
|
|
@ -3,16 +3,12 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
{
|
{
|
||||||
public interface IThreadPool : IScheduler
|
public interface IThreadPool : IScheduler
|
||||||
{
|
{
|
||||||
void Complete(TaskCompletionSource<object> tcs);
|
|
||||||
void Cancel(TaskCompletionSource<object> tcs);
|
|
||||||
void Error(TaskCompletionSource<object> tcs, Exception ex);
|
|
||||||
void Run(Action action);
|
void Run(Action action);
|
||||||
void UnsafeRun(WaitCallback action, object state);
|
void UnsafeRun(WaitCallback action, object state);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
|
|
@ -29,42 +28,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Complete(TaskCompletionSource<object> tcs)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tcs.TrySetResult(null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.LogError(0, e, "InlineLoggingThreadPool.Complete");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Cancel(TaskCompletionSource<object> tcs)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tcs.TrySetCanceled();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.LogError(0, e, "InlineLoggingThreadPool.Cancel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Error(TaskCompletionSource<object> tcs, Exception ex)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tcs.TrySetException(ex);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.LogError(0, e, "InlineLoggingThreadPool.Error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnsafeRun(WaitCallback action, object state)
|
public void UnsafeRun(WaitCallback action, object state)
|
||||||
{
|
{
|
||||||
action(state);
|
action(state);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
|
|
@ -13,8 +12,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
private readonly IKestrelTrace _log;
|
private readonly IKestrelTrace _log;
|
||||||
|
|
||||||
private WaitCallback _runAction;
|
private WaitCallback _runAction;
|
||||||
private WaitCallback _cancelTcs;
|
|
||||||
private WaitCallback _completeTcs;
|
|
||||||
|
|
||||||
public LoggingThreadPool(IKestrelTrace log)
|
public LoggingThreadPool(IKestrelTrace log)
|
||||||
{
|
{
|
||||||
|
|
@ -25,8 +22,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
// call stack for exceptions and profiling else it shows up as LoggingThreadPool.ctor>b__4_0
|
// call stack for exceptions and profiling else it shows up as LoggingThreadPool.ctor>b__4_0
|
||||||
// and you aren't sure which of the 3 functions was called.
|
// and you aren't sure which of the 3 functions was called.
|
||||||
RunAction();
|
RunAction();
|
||||||
CompleteTcs();
|
|
||||||
CancelTcs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunAction()
|
private void RunAction()
|
||||||
|
|
@ -45,38 +40,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CompleteTcs()
|
|
||||||
{
|
|
||||||
// Capture _log in a singleton closure
|
|
||||||
_completeTcs = (o) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((TaskCompletionSource<object>)o).TrySetResult(null);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.LogError(0, e, "LoggingThreadPool.Complete");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CancelTcs()
|
|
||||||
{
|
|
||||||
// Capture _log in a singleton closure
|
|
||||||
_cancelTcs = (o) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((TaskCompletionSource<object>)o).TrySetCanceled();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.LogError(0, e, "LoggingThreadPool.Cancel");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Run(Action action)
|
public void Run(Action action)
|
||||||
{
|
{
|
||||||
ThreadPool.QueueUserWorkItem(_runAction, action);
|
ThreadPool.QueueUserWorkItem(_runAction, action);
|
||||||
|
|
@ -87,32 +50,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||||
ThreadPool.QueueUserWorkItem(action, state);
|
ThreadPool.QueueUserWorkItem(action, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Complete(TaskCompletionSource<object> tcs)
|
|
||||||
{
|
|
||||||
ThreadPool.QueueUserWorkItem(_completeTcs, tcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Cancel(TaskCompletionSource<object> tcs)
|
|
||||||
{
|
|
||||||
ThreadPool.QueueUserWorkItem(_cancelTcs, tcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Error(TaskCompletionSource<object> tcs, Exception ex)
|
|
||||||
{
|
|
||||||
// ex and _log are closure captured
|
|
||||||
ThreadPool.QueueUserWorkItem((o) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((TaskCompletionSource<object>)o).TrySetException(ex);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_log.LogError(0, e, "LoggingThreadPool.Error");
|
|
||||||
}
|
|
||||||
}, tcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Schedule(Action action)
|
public void Schedule(Action action)
|
||||||
{
|
{
|
||||||
Run(action);
|
Run(action);
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
|
|
||||||
using Microsoft.AspNetCore.Testing;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|
||||||
{
|
|
||||||
public class LoggingThreadPoolTests
|
|
||||||
{
|
|
||||||
[Fact]
|
|
||||||
public void TcsContinuationErrorsDontGetLoggedAsGeneralErrors()
|
|
||||||
{
|
|
||||||
var testLogger = new TestApplicationErrorLogger();
|
|
||||||
var testKestrelTrace = new TestKestrelTrace(testLogger);
|
|
||||||
var threadPool = new LoggingThreadPool(testKestrelTrace);
|
|
||||||
|
|
||||||
var completeTcs = new TaskCompletionSource<object>();
|
|
||||||
ThrowSynchronously(completeTcs.Task);
|
|
||||||
threadPool.Complete(completeTcs);
|
|
||||||
|
|
||||||
var errorTcs = new TaskCompletionSource<object>();
|
|
||||||
ThrowSynchronously(errorTcs.Task);
|
|
||||||
threadPool.Error(errorTcs, new Exception());
|
|
||||||
|
|
||||||
var cancelTcs = new TaskCompletionSource<object>();
|
|
||||||
ThrowSynchronously(cancelTcs.Task);
|
|
||||||
threadPool.Cancel(cancelTcs);
|
|
||||||
|
|
||||||
Assert.Throws<AggregateException>(() =>
|
|
||||||
Task.WhenAll(completeTcs.Task, errorTcs.Task, cancelTcs.Task).Wait());
|
|
||||||
|
|
||||||
Assert.Equal(0, testLogger.TotalErrorsLogged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThrowSynchronously(Task task)
|
|
||||||
{
|
|
||||||
task.ContinueWith(_ =>
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}, TaskContinuationOptions.ExecuteSynchronously);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue