You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Calling Dispose an a NamedPipeServerStream which is currently inside WaitForConnectionAsync does not cancel the underlying listen event when there are multiple NamedPipeServerStream instances active on the same named pipe. This can result in future NamedPipeClientStream.Connect calls going to the disposed NamedPipeServerStream instead of the non-disposed ones.
Consider the example below. This will start two NamedPipeServerStream instances on a single pipe name, then it will dispose the first one and start a client connection to the pipe. The connection will succeed but it connects to the disposed NamedPipeServerStream, not the active one. The stream can then be used without error.
Example code:
using System;using System.IO.Pipes;using System.Threading;using System.Threading.Tasks;classProgram{staticasync Task Main(string[]args){varpipeName= Guid.NewGuid().ToString();usingvarserver1= CreateServer();usingvarserver2= CreateServer();varwait1= server1.WaitForConnectionAsync();
server1.Dispose();varwaitTask= Task.Run(async()=>{await server2.WaitForConnectionAsync(); Console.WriteLine("Server 2 got a connection");});varclient=new NamedPipeClientStream(pipeName);await client.ConnectAsync();
Console.WriteLine("Client connected");await wait1;
Console.WriteLine(wait1.Status);// Can still use server1 even though it's disposedawait server1.WriteAsync(newbyte[]{42},0,1);varbuffer=newbyte[1];await client.ReadAsync(buffer,0,1);
Console.WriteLine(buffer[0]);// Prints 42
Console.WriteLine("At the end");
NamedPipeServerStream CreateServer()=>new NamedPipeServerStream(
pipeName,
PipeDirection.InOut,
maxNumberOfServerInstances:10,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous);}}
When run on Unix this code will output:
Client connected
RanToCompletion
42
At the end
When run on Windows this code will output:
Server 2 got a connection
Client connected
Unhandled exception. System.IO.IOException: The pipe has been ended.
at System.IO.Pipes.ConnectionCompletionSource.HandleError(Int32 errorCode)
at System.IO.Pipes.PipeCompletionSource`1.CompleteCallback(Int32 resultState)
at System.IO.Pipes.PipeCompletionSource`1.AsyncCallback(UInt32 errorCode, UInt32 numBytes) at System.IO.Pipes.ConnectionCompletionSource.AsyncCallback(UInt32 errorCode, UInt32 numBytes)
at System.IO.Pipes.PipeCompletionSource`1.<>c.<.ctor>b__11_0(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOverlapped)
at System.Threading.ThreadPoolBoundHandleOverlapped.CompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pNativeOverlapped)
--- End of stack trace from previous location ---
at Program.Main(String[] args) in P:\temp\console\Program.cs:line 26
at Program.<Main>(String[] args)
The text was updated successfully, but these errors were encountered:
Hello,
I have reproduced your issue on a local dev setup with .NET 5.0.6 and .NET 6.0.0-preview.3.
I am working on a fix proposal. I will open a PR against the main branch, if needed we will see whether it can be easily backported.
On Windows, only when the pipe server stream is opened with PipeOptions.Asynchronous, disposing of it causes WaitForConnectionAsync() to fault with an IOException with HResult == -2147024787. Otherwise, WaitForConnectionAsync() never completes until a client connects.
Calling
Dispose
an aNamedPipeServerStream
which is currently insideWaitForConnectionAsync
does not cancel the underlying listen event when there are multipleNamedPipeServerStream
instances active on the same named pipe. This can result in futureNamedPipeClientStream.Connect
calls going to the disposedNamedPipeServerStream
instead of the non-disposed ones.Consider the example below. This will start two
NamedPipeServerStream
instances on a single pipe name, then it will dispose the first one and start a client connection to the pipe. The connection will succeed but it connects to the disposedNamedPipeServerStream
, not the active one. The stream can then be used without error.Example code:
When run on Unix this code will output:
When run on Windows this code will output:
The text was updated successfully, but these errors were encountered: