Jeffrey Price
Jeffrey Price

Reputation: 51

Windows named pipe intermittant connection problems

I've got a pair of windows processes that communicate via named pipes. The server calls CreateNamedPipeW and the client calls CreateFileW to open the same named pipe. Some times this works fine, and then can send messages back and forth. Some times this fails with the error ERROR_PIPE_BUSY on both ends.

I'm pretty sure there is exactly one copy of each of the server and client process. I'm also sure that there is exactly one thread on each end that does the pipe management. i.e. I don't think my problem is that there are multiple producers or consumers.

server:

OVERLAPPED openServerOverlapped;
...
SECURITY_ATTRIBUTES sa;
// ...
server = CreateNamedPipeW(
    pipeName.c_str(),
    PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
    1,
    PIPE_BUFFER_SIZE,
    PIPE_BUFFER_SIZE,
    NMPWAIT_USE_DEFAULT_WAIT,
    &sa
);
if (server != INVALID_HANDLE_VALUE) {
    auto lastError = ConnectNamedPipe(server, &openServerOverlapped) == FALSE
        ? GetLastError()
        : ERROR_PIPE_CONNECTED;
    if (lastError == ERROR_IO_PENDING) {
        DWORD bytesTransferred = 0;
        lastError = GetOverlappedResultEx(
            server, &openServerOverlapped, &bytesTransferred,
            CLIENT_CONNECT_TIMEOUT, FALSE
        ) == FALSE
            ? GetLastError()
            : ERROR_PIPE_CONNECTED;
    }
    if (lastError == ERROR_PIPE_CONNECTED) {
        // start reading messages
    } else {
        // error handling, looks like "ConnectNamedPipe error..."
    }
} else {
    // error handling, looks like "CreateNamedPipeW error..."
}

We sometimes get errors like the following

got error: CreateNamedPipeW error: LastError=000000e7, All pipe instances are busy.

e7 is ERROR_PIPE_BUSY, which matches the erorr message we got from FormatMessage

When this is happening we get similar errors out of our client. Client is actually c#, but uses marshalling to call the same win32 APIs.

client:

while (true) {
    // ...
    pipeHandle = CreateFileW(fileName,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        IntPtr.Zero,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        IntPtr.Zero
    );
    if (pipeHandle.ToInt32() == INVALID_HANDLE_VALUE) {
        // error handling, looks like "Failed to create pipe client..."
        Thread.Sleep(5000);
        continue;
    }
    // ...
}

We get logging like:

Failed to create pipe client, win32 error: 231

231 = e7, so same error: ERROR_PIPE_BUSY

Upvotes: 0

Views: 1106

Answers (1)

Jeaninez - MSFT
Jeaninez - MSFT

Reputation: 4032

According to the documentation:

Named Pipe Client

A named pipe client uses the CreateFile function to open a handle to a named pipe. If the pipe exists but all of its instances are busy, CreateFile returns INVALID_HANDLE_VALUE and the GetLastError function returns ERROR_PIPE_BUSY.

The reason for the error is that all of its instances are busy.

I suggest you try to use the CreateNamedPipe() function to create another instance of a named pipe. And also try to use the DisconnectNamedPipe function to disconnect the server end of a named pipe instance from a client process, and then you can connect that instance to another client by using the ConnectNamedPipe() function.

I suggest you refer to the example: Multithreaded Pipe Server

Upvotes: 1

Related Questions