Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NamedPipeServerStream.BeginWaitForConnection fails with System.IO.Exception: The pipe is being closed

I have written a simple async NamedPipeStreamServer process in C#, the heart of which is:

public void Listen()
{
    bool shuttingDown = false;
    while (!shuttingDown)
    {
        NamedPipeServerStream serverStream =
            new NamedPipeServerStream(
                "bobasdfpipe",
                PipeDirection.InOut,
                254,
                PipeTransmissionMode.Message,
                PipeOptions.Asynchronous);

        IAsyncResult connectionResult = 
                serverStream.BeginWaitForConnection(
                    this.HandleConnection,
                    serverStream);

        int waitResult =
            WaitHandle.WaitAny(
                new[]
                    {
                        this.ShutdownEvent,
                        connectionResult.AsyncWaitHandle
                    });
        switch (waitResult)
        {
            case 0:
                // this.ShutdownEvent
                shuttingDown = true;
                break;

            case 1:
                // connectionResult.AsyncWaitHandle
                serverStream.EndWaitForConnection(connectionResult);
                break;
        }
    }
}

I have also written a simple client for it. The client (which is not asynchronous) does nothing more than open the pipe and then exit:

static void Main(string[] args)
{
    using (
        NamedPipeClientStream clientStream =
            new NamedPipeClientStream(
                ".",
                "bobasdfpipe",
                PipeDirection.InOut))
    {
        clientStream.Connect();
    }
}

If I start the server up, and then start up a client, or multiple clients, everything seems to work fine.

If I start up a client without having started the server, the client hangs on the Connect() call until I start up the server, but then when I start the server, the server crashes with a System.IO.Exception on the BeginWaitForConnection() call, saying "The pipe is being closed."

I've found other people having "The pipe is being closed" errors on BeginWaitForConnection(), but they're all caused by attempting a second BeginWaitForConnection() call on the same NamedPipeServerStream instance. That's not what's going on here - I create a different NamedPipeServerStream instance for each BeginWaitForConnection() call, and even if I didn't, it is failing on the very first BeginWaitForConnection() call anyway.

Am I doing something wrong? Or is this just normal - a named pipe client that is waiting for the server to come up will cause "The pipe is being closed" on the server's first BeginWaitForConnection() call?

I have noticed that if I just try again - i.e. absorb the exception and do another BeginWaitForConnection() - then I get one such exception for every client that had been waiting for the server to come up, but after dealing with all of those, the server seems to work fine thereafter.

EDIT: Here's the HandleConnection method, but I don't think it even hits this code:

private void HandleConnection(IAsyncResult iar)
{
    NamedPipeServerStream serverStream =
        (NamedPipeServerStream)iar.AsyncState;

    Log.Info("So, that happened.");
    Thread.Sleep(1000);
    Log.Info("Giving up.");
}
like image 384
Bob Vesterman Avatar asked Oct 19 '22 12:10

Bob Vesterman


1 Answers

It appears that Client closes the connection before it is completely handled by Server. It happens because clientStream.Dispose() is called right after clientStream.Connect() and the connection that was about to be established gets terminated. Hint: try to add Thread.Sleep(100) right after clientStream.Connect().

Am I doing something wrong? Or is this just normal - a named pipe client that is waiting for the server to come up will cause "The pipe is being closed" on the server's first BeginWaitForConnection() call?

Regardless of what the client does the server code should be able to gracefully handle this sequence of events by catching IOException and discarding the server's pipe handle.

   NamedPipeServerStream serverStream =
        new NamedPipeServerStream(
            "bobasdfpipe",
            PipeDirection.InOut,
            254,
            PipeTransmissionMode.Message,
            PipeOptions.Asynchronous);

    try 
    {  
        IAsyncResult connectionResult = serverStream.BeginWaitForConnection(
                this.HandleConnection,
                serverStream);


       int waitResult =
           WaitHandle.WaitAny(
               new[]
                {
                    this.ShutdownEvent,
                    connectionResult.AsyncWaitHandle
                });
        switch (waitResult)
        {
          case 0:
            // this.ShutdownEvent
            shuttingDown = true;
            break;

          case 1:
            // connectionResult.AsyncWaitHandle
               serverStream.EndWaitForConnection(connectionResult);
               break;
         }    

    }
    catch(IOException)
    {
        // Connection terminated by client, close server pipe's handle
        serverStream.Close();
        continue;
    }
like image 133
alexm Avatar answered Oct 21 '22 04:10

alexm