If you get ERROR_PIPE_BUSY in a call to CreateFile () in the client, you need to call WaitNamedPipe () and then try again when it returns. If you get a zero return from WaitNamedPipe (), it means that it was disconnected without the ability to access the pipe. You will never see this happen if you skip NMPWAIT_WAIT_FOREVER as a timeout.
You also need to keep in mind that the pipe may again become busy between the WaitNamedPipe () timeout and CreateFile () is called; so you need to do this in a loop. Like this:
while (true) { hPipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hPipe == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { if (!WaitNamedPipe(pipeName, NMPWAIT_USE_DEFAULT_WAIT)) continue; // timeout, try again } else return false; // error } else break; // success }
EDIT:
I simplified your code and now it works fine. A working server and client follow.
Server:
#include <windows.h> #include <stdio.h> int main(void) { HANDLE pipe; const DWORD BUFFER_SIZE = 1024; pipe = CreateNamedPipe("\\\\.\\pipe\\testpipe1", PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFFER_SIZE, // output buffer size BUFFER_SIZE, // input buffer size 2000, // client time-out NULL); if (pipe == INVALID_HANDLE_VALUE) { printf("Error while creating pipe\n"); return -1; } printf("Connecting to named pipe\n"); int ac; for (ac=0; ac<2; ac++) { // Wait for some input. This helps me to start the client in other terminal. printf("Connecting...\n"); ConnectNamedPipe(pipe, 0); printf("Connect pipe returned.\n"); // Wait for some input. char * message = "Test message"; DWORD bytes_written; if (!WriteFile(pipe, message, strlen(message)+1, &bytes_written, NULL)) { DWORD er = GetLastError(); char errs[200]; sprintf_s(errs, "Error : %ld", er); printf("Error communicating to client.\n"); printf(errs); } printf("Written to pipe\n"); FlushFileBuffers(pipe); if (!DisconnectNamedPipe(pipe)) { printf("Disconnect failed %d\n", GetLastError()); } else { printf("Disconnect successful\n"); } } }
Client:
#include <windows.h> #include <stdio.h> int main(void) { HANDLE hPipe; while (1) { printf("Returned\n"); hPipe = CreateFile("\\\\.\\pipe\\testpipe1", GENERIC_READ, 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file // Break if the pipe handle is valid. if (hPipe != INVALID_HANDLE_VALUE) break; // Exit if an error other than ERROR_PIPE_BUSY occurs. if (GetLastError() != ERROR_PIPE_BUSY) { printf("Could not open pipe %d\n", GetLastError()); return -1; } // All pipe instances are busy, so wait for sometime. if ( ! WaitNamedPipe("\\\\.\\pipe\\testpipe1", NMPWAIT_USE_DEFAULT_WAIT)) { printf("Could not open pipe: wait timed out.\n"); } } char *message = "hello"; DWORD cbToWrite = (strlen(message)+1)*sizeof(message[0]); DWORD bytes_to_read = 2000; char * buf = reinterpret_cast<char *>(malloc(bytes_to_read)); DWORD bytes_read; printf("Waiting for read\n"); bytes_read = 0; ReadFile(hPipe, buf, bytes_to_read, &bytes_read, 0); if (bytes_read <= 0) { printf("ReadFile from pipe failed. GLE \n"); } else printf("Read %d bytes: %s\n", bytes_read, buf); CloseHandle(hPipe); return 0; }