parent
0ac478858d
commit
6a403d231e
|
|
@ -3,16 +3,12 @@
|
|||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.System.IO.Pipelines;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
||||
{
|
||||
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 UnsafeRun(WaitCallback action, object state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
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)
|
||||
{
|
||||
action(state);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
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 WaitCallback _runAction;
|
||||
private WaitCallback _cancelTcs;
|
||||
private WaitCallback _completeTcs;
|
||||
|
||||
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
|
||||
// and you aren't sure which of the 3 functions was called.
|
||||
RunAction();
|
||||
CompleteTcs();
|
||||
CancelTcs();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(_runAction, action);
|
||||
|
|
@ -87,32 +50,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
|
|||
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)
|
||||
{
|
||||
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