Skip to content

AnonymousPipeClientStream.ReadAsync does not seem to support cancellation #23638

@tintoy

Description

@tintoy

Hi.

After some experimentation, it seems to me that unlike NamedPipeClientStream, AnonymousPipeClientStream (or AnonymousPipeServerStream for that matter) does not support cancellation (because there's no way to open the pipe in async mode and so Stream.ReadAsync is used instead of PipeStream.ReadAsyncCore). This is a little painful because it means there's no way to "unblock" a pending read or write on that stream when the stream contains no data.

Here's a simple repro that shows what I'm trying to do. It works for named pipes, but not for anonymous ones:

NamedPipeServerStream source = new NamedPipeServerStream("pipe-test", PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
NamedPipeClientStream destination = new NamedPipeClientStream(".", "pipe-test", PipeDirection.In, PipeOptions.Asynchronous);
await destination.ConnectAsync();

CancellationTokenSource cancellationSource = new CancellationTokenSource();

byte[] buffer = new byte[10];
Task<int> readTask = destination.ReadAsync(buffer, 0, buffer.Length, cancellationSource.Token);

// Right now, readTask is blocked waiting for data.
Task timeout = Task.Delay(TimeSpan.FromSeconds(1));
Task winner = await Task.WhenAny(readTask, timeout);
Assert.Equal(timeout, winner);

cancellationSource.Cancel();

// readTask will now fault with TaskCanceledException
timeout = Task.Delay(TimeSpan.FromSeconds(5));
winner = await Task.WhenAny(readTask, timeout);
Assert.Equal(readTask, winner);

// Prove that it was canceled via the correct CancellationToken
TaskCanceledException cancelled = await Assert.ThrowsAsync<TaskCanceledException>(() => readTask);
Assert.Equal(cancellationSource.Token, cancelled.CancellationToken);

Is this by design, or simply something nobody has gotten around to, yet? Because it looks like it should be possible to implement by constructing the base PipeStream with isAsync: true to use the correct code-path.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions