Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Cancel Accept on dispose
  • Loading branch information
manandre committed Jun 1, 2021
commit ef60a2f194269baf1bfbabbea77710a359c2ea4a
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public sealed partial class NamedPipeServerStream : PipeStream
private int _inBufferSize;
private int _outBufferSize;
private HandleInheritability _inheritability;
private CancellationTokenSource _internalTokenSource = new CancellationTokenSource();

private void Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances,
PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
Expand Down Expand Up @@ -77,8 +78,29 @@ public Task WaitForConnectionAsync(CancellationToken cancellationToken)
Task.FromCanceled(cancellationToken) :
WaitForConnectionAsyncCore();

async Task WaitForConnectionAsyncCore() =>
HandleAcceptedSocket(await _instance!.ListeningSocket.AcceptAsync(cancellationToken).ConfigureAwait(false));
async Task WaitForConnectionAsyncCore()
{
Socket acceptedSocket;
CancellationTokenSource? linkedTokenSource = null;
try
{
linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_internalTokenSource.Token, cancellationToken);
acceptedSocket = await _instance!.ListeningSocket.AcceptAsync(linkedTokenSource.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
//if cancellation was via external token, throw an OCE
cancellationToken.ThrowIfCancellationRequested();

throw new IOException(SR.IO_PipeBroken);
}
finally
{
linkedTokenSource?.Dispose();
}

HandleAcceptedSocket(acceptedSocket);
}
}

private void HandleAcceptedSocket(Socket acceptedSocket)
Expand All @@ -87,12 +109,6 @@ private void HandleAcceptedSocket(Socket acceptedSocket)

try
{
if (State == PipeState.Closed)
{
// Pipe was closed/disposed during the connection phase, handle it as a broken pipe
throw new IOException(SR.IO_PipeBroken);
}

if (IsCurrentUserOnly)
{
uint serverEUID = Interop.Sys.GetEUid();
Expand Down Expand Up @@ -122,9 +138,20 @@ private void HandleAcceptedSocket(Socket acceptedSocket)
State = PipeState.Connected;
}

internal override void DisposeCore(bool disposing) =>
internal override void DisposeCore(bool disposing)
{
Interlocked.Exchange(ref _instance, null)?.Dispose(disposing); // interlocked to avoid shared state problems from erroneous double/concurrent disposes

if (disposing)
{
if (State != PipeState.Closed)
{
_internalTokenSource.Cancel();
}
_internalTokenSource.Dispose();
}
}

public void Disconnect()
{
CheckDisconnectOperations();
Expand Down