FubarDevelopment / FtpServer

Portable FTP server written in .NET
http://fubardevelopment.github.io/FtpServer/
MIT License
472 stars 161 forks source link

Cancellation of FtpConnection.ReadFromStreamAsync causes UnobservedTaskException #131

Open cjzzz opened 2 years ago

cjzzz commented 2 years ago

In FtpConnection.ReadFromStreamAsync, readTask is started using the cancellation token passed into the method, but tcs is also created which has its result set when the cancellation token is cancelled:

protected override async Task<int> ReadFromStreamAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken)
{
    var readTask = Stream
       .ReadAsync(buffer, offset, length, cancellationToken);

    var tcs = new TaskCompletionSource<object?>();
    using var registration = cancellationToken.Register(() => tcs.TrySetResult(null));
    var resultTask = await Task.WhenAny(readTask, tcs.Task)
       .ConfigureAwait(false);

    if (cancellationToken.IsCancellationRequested)
    {
        Logger?.LogTrace("Cancelled through CancellationToken");
        return 0;
    }
...

This can cause resultTask to complete when tcs.Task is complete, and the exception from the cancellation of readTask is never observed. causing an UnobservedTaskException.

fubar-coder commented 2 years ago

Nice catch!