System.IO.Exception: Pipe is broken
Asked Answered
W

4

24

I have two .NET applications that talk to each other over a named pipe. Everything is great the first time through, but after the first message is sent, and the server is going to listen again, the WaitForConnection() method throws a System.IO.Exception with message Pipe is broken.
Why am I getting this exception here? This is my first time working with pipes, but a similar pattern has worked for me in the past with sockets.

Code ahoy!
Server:

using System.IO.Pipes;

static void main()
{
    var pipe = new NamedPipeServerStream("pipename", PipeDirection.In);
    while (true)
    {
        pipe.Listen();
        string str = new StreamReader(pipe).ReadToEnd();
        Console.Write("{0}", str);
    }
}

Client:

public void sendDownPipe(string str)
{
    using (var pipe = new NamedPipeClientStream(".", "pipename", PipeDirection.Out))
    {
        using (var stream = new StreamWriter(pipe))
        {
            stream.Write(str);
        }
    }
}

The first call to sendDownPipe gets the server to print the message I send just fine, but when it loops back up to listen again, it poops.

Whitleywhitlock answered 21/5, 2009 at 22:3 Comment(1)
I think the reason you are having this issue is because of the line "new StreamReader(pipe)". The scope of created stream reader is the first while loop and it is then recreated. However stream readers behavior is to close the stream they are wrapping - thus once it is out of scope it will close the pipe stream. You can try moving its declaration out of the while loop and check (P.S: I did not personally try if the code works if you do so - just wanted to add a comment rather than answer)Responsory
H
24

I'll post my code that seems to work - I was curious since I never did anything with pipes. I didn't find the class you name for the server-side in the relevant namespace, so here's the code based on the NamedPipeServerStream. The callback stuff is just because I couldn't be bothered with two projects.

NamedPipeServerStream s = new NamedPipeServerStream("p", PipeDirection.In);
Action<NamedPipeServerStream> a = callBack;
a.BeginInvoke(s, ar => { }, null);
...
private void callBack(NamedPipeServerStream pipe)
{
  while (true)
  {
    pipe.WaitForConnection();
    StreamReader sr = new StreamReader(pipe);
    Console.WriteLine(sr.ReadToEnd());
    pipe.Disconnect();
  }
}

And the client does this:

using (var pipe = new NamedPipeClientStream(".", "p", PipeDirection.Out))
using (var stream = new StreamWriter(pipe))
{
  pipe.Connect();
  stream.Write("Hello");
}

I can repeat above block multiple times with the server running, no prob.

Hangnail answered 21/5, 2009 at 22:49 Comment(5)
That did the trick. I guess theres no implicit disconnect when a client falls off the other end. Thanks.Whitleywhitlock
This gives me an error that the pipe isn't connected on this line: using (var stream = new StreamWriter(pipe))Landri
Doesn't seem to work between processes. The pipe.Disconnect() blows up with a "Cannot access a closed pipe"Lieabed
Here's what I ended up doing: https://mcmap.net/q/146396/-best-way-to-implement-singleton-in-a-console-application-cLieabed
@Sean, when your StreamWriter is disposed by the using(), the underlying pipe is closed, too. You can avoid that by creating the StreamWriter with new StreamWriter(pipe, Encoding.UTF8, -1, true). And you need to create the reader with a similar overload.Ardie
H
16

The problem for me has occurred when I would call pipe.WaitForConnection() from the server, after the client disconnected. The solution is to catch the IOException and call pipe.Disconnect(), and then call pipe.WaitForConnection() again:

while (true)
{
    try
    {
        _pipeServer.WaitForConnection();
        break;
    }
    catch (IOException)
    {
        _pipeServer.Disconnect();
        continue;
    }            
 }
Henryhenryetta answered 28/2, 2012 at 15:21 Comment(0)
K
0

I ran into a similar issue when I put Environment.Exit(0) at the end of my Main method, which apparently killed the entire process even though I thought the code was unreachable (because it was after a while loop waiting for a different thread to stop).

Kapoor answered 31/5, 2022 at 22:27 Comment(0)
T
-3

I had the same problem - it is caused by disposing server's StreamReader by Using...End Using, which also take down NamedPipeServerStream. Solution is simply don't Using...End Using it and trust in garbage collector.

Thai answered 29/10, 2019 at 10:46 Comment(1)
If you don't use using consider using Dispose(). Hoping that GC will free the memory is a bad approach.Chelsae

© 2022 - 2024 — McMap. All rights reserved.