-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
I am referencing Formitable.BetterStack.Logger.Microsoft v0.1.2 and I get the following exception when my app is terminating:
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred. (The CancellationTokenSource has been disposed.)
Source=System.Private.CoreLib
StackTrace:
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait(TimeSpan timeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait(TimeSpan timeout)
at Formitable.BetterStack.Logger.Microsoft.BetterStackLoggerProvider.Dispose()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose()
at Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
at Picton.IntegrationTests.Program.<Main>d__0.MoveNext() in D:\_build\Picton\Source\Picton.IntegrationTests\Program.cs:line 25
at Picton.IntegrationTests.Program.<Main>d__0.MoveNext() in D:\_build\Picton\Source\Picton.IntegrationTests\Program.cs:line 26
at Picton.IntegrationTests.Program.<Main>()
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
ObjectDisposedException: The CancellationTokenSource has been disposed.
This is due to the fact that the cancellation token is disposed in the Dispose method like so:
_cancellationTokenSource.Dispose();meanwhile the _flushTask is still running and one of the lines in this flush task is the following:
while (!_cancellationTokenSource.IsCancellationRequested)This line causes the exception because the cancellation token has been disposed.
I propose the following changes in the Dispose method to resolve this problem:
- Invoke
Cancel()on the cancellation token source rather than disposing it. This ensures that no exception is thrown in "_flushTask" and_cancellationTokenSource.IsCancellationRequestedcan be evaluated without problem. It will returntrue, causing the task to stop gracefully which is the desired behavior. - There's a possibility that a few messages might still be in the queue when "_flushTask" is stopped. Therefore the
try ... catch ...code inDisposeneeds to be altered to process these remaining messages. - Add a
finallysection to thetry ... catch ...where the cancellation token source can be safely disposed.
I will submit a PR where I implement the changes I propose.
For reference, this is what my app looks like:
namespace Picton.IntegrationTests
{
public class Program
{
public static async Task Main()
{
var cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};
var services = new ServiceCollection();
ConfigureServices(services);
using var serviceProvider = services.BuildServiceProvider();
var app = serviceProvider.GetService<IHostedService>();
await app.StartAsync(cts.Token).ConfigureAwait(false);
}
private static void ConfigureServices(ServiceCollection services)
{
services.AddHostedService<TestsRunner>();
services
.AddLogging(logging =>
{
var betterStackToken = Environment.GetEnvironmentVariable("BETTERSTACK_TOKEN");
if (!string.IsNullOrEmpty(betterStackToken))
{
logging.AddBetterStackLogger(options =>
{
options.SourceToken = betterStackToken;
});
}
logging.AddSimpleConsole(options =>
{
options.SingleLine = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
});
logging.AddFilter("*", LogLevel.Debug);
});
}
}
}Metadata
Metadata
Assignees
Labels
No labels