Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm trying to write in a named pipe and read back the same thing. Consider the following code snippet (the error handling is stripped for brevity):

const char * pipeName = "\\\\.\\pipe\\pipe";
const char * buffWrite = "SOME TEXT";
unsigned buffLength = strlen(buffWrite);
char buffRead[1024];
DWORD nWritten, nRead;
HANDLE hPipe = CreateNamedPipe(pipeName,
PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, 0);
HANDLE hFile = CreateFile(pipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
WriteFile(hFile, buffWrite, buffLength, &nWritten, 0);
CloseHandle(hFile);
//the next line fails with >>All pipe instances are busy.<<
hFile = CreateFile(pipeName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
ReadFile(hFile, buffRead, buffLength, &nRead, 0);

However when I try reopen the pipe for reading the CreateFile call fails with "All pipes are busy."

What am I missing here?

EDIT. Peeking works fine, i.e.

DWORD nRead, nTotal, nLeft;
PeekNamedPipe(hPipe, buffRead, buffLength, &nRead, &nTotal, &nLeft);

returns the written data correctly.

REMARK. This is a proof of concept for something larger. No new threads and processes will be involved.

That error code tells you that somebody else is already reading from the pipe. There can be only one reader, having more than one would just create chaos when each reader gets a random bit of the data. Nothing in your snippet makes it obvious what other code might be reading. But clearly it is buggy code. – Hans Passant Jul 29, 2015 at 12:38

The reason you're getting that specific error code is that you only created one instance of the named pipe, and you've already used it. (You can create a new instance by calling CreateNamedPipe a second time, or you can reuse an existing instance by calling DisconnectNamedPipe.)

However, based on your commentary, I believe you want the call to ReadFile to retrieve the data written by the call to WriteFile, i.e., you want the same instance of the pipe, not a new one.

To do that, do not open a new handle. Use the existing handle, hPipe.

(Note that each pipe instance has two ends; a server end and a client end. The handle from CreateNamedPipe is always to the server end, and the handle from CreateFile is always to the client end. Data written to the server end can only be read from the client end, and vice-versa.)

You are trying to use named pipe as some kind of buffer - client connects to it, puts some data, then disconnects, after that other client connects and retrieves this data. This is invalid approach, named pipe is just that - a pipe, it has two sides - server side and client side, server and client could communicate through it. Usual pipe usage scenario:

  • Server creates named pipe using CreateNamedPipe function;
  • Server begin waiting for the client connections using ConnectNamedPipe method;
  • Client creates its side of the pipe using CreateFile API call;
  • Server and client communicate using ReadFile/WriteFile;
  • Pipe is closed with DisconnectNamedPipe and could be reactivated again with ConnectNamedPipe.
  • You could see complete example in the MSDN here.

    So is reading and writing a given named pipe from the same thread forbidden? Could you point me to a place where this is explicitly stated? – negipezu Jul 29, 2015 at 12:57 No it is not forbidden. But if you write some data using your hFile pipe handle, you must read it using hPipe. In your example you close connection after writing data so it is lost. – Ari0nhh Jul 29, 2015 at 13:01 Also it is worth pointing out that named pipes are mechanism for the interprocess communication. Using them in the single thread is pointless. – Ari0nhh Jul 29, 2015 at 13:03 @Ari0nnh. No, it's not lost after closing hFile. I did a PeekNamedPipe right after closing hFile, and the string was in there. – negipezu Jul 29, 2015 at 13:08 Closing the client end of a pipe doesn't discard the data, that only happens when the server end is closed or disconnected. – Harry Johnston Jul 29, 2015 at 22:59

    It is because both extremities of the pipe have allready be opened (*)...

    First was opened with the CreatePipe call, the other was with the first CreateFile call. You should not try to open one time more the pipe, but simply read from the hPipe HANDLE :

    const char * pipeName = "\\\\.\\pipe\\pipe";
    const char * buffWrite = "SOME TEXT";
    unsigned buffLength = strlen(buffWrite);
    char buffRead[1024];
    DWORD nWritten, nRead;
    HANDLE hPipe = CreateNamedPipe(pipeName,
    PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, 0);
    HANDLE hFile = CreateFile(pipeName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    WriteFile(hFile, buffWrite, buffLength, &nWritten, 0);
    CloseHandle(hFile);
    ReadFile(hPipe, buffRead, buffLength, &nRead, 0); // nRead=9, buffRead="SOME TEXT"
    

    (*) You did specify PIPE_UNLIMITED_INSTANCES for the nMaxInstances parameter in CreateNamedPipe call, but as you never called ConnectNamedPipe to create other endpoints, only one CreateFile was allowed.

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.