Windows Named Pipe issue: Error code 233 alternates

MrHuggies picture MrHuggies · Dec 15, 2010 · Viewed 15.2k times · Source

I need help on my application I am making. It's a simple program that responds to command line parameters. If the application is invoked for the first time, it starts up as a pipe server (blocking, non-overlapped) on another thread devoted to it, while the main thread does something else. Now, the user can still invoke the application using the same application executable and command line parameters but since its not the first instance of the application, it passes the command line parameters to the first instance using the pipe, then kills the itself. So, it's like a singleton process in patterns-lingo.

Ideally, it should be like this:

app.exe "first"    // starts app.exe as a pipe server and prints "first"
app.exe "second"   // client process causes server instance to print "second"
app.exe "third"    // client process causes server instance to print "third"
app.exe "fourth"   // client process causes server instance to print "fourth"
app.exe "fifth"    // client process causes server instance to print "fifth"
app.exe -quit      // client process causes server instance to terminate.

Now, my only problem is, when I do the above lines this happens:

app.exe "first"    // starts app.exe as a pipe server and prints "first"
app.exe "second"   // client process returns a GetLastError code of 233
app.exe "third"    // client process causes server instance to print "third"
app.exe "fourth"   // client process returns a GetLastError code of 233
app.exe "fifth"    // client process causes server instance to print "fifth"
app.exe -quit      // client process returns a GetLastError code of 233

My pipe server code goes something like this (pseudo code):

CreateNamedPipe();
// Code below now runs on a separate thread...
while( !Quit )
{
    if( ConnectNamedPipe() is successful )
    {
        if( PeekNamedPipe() has a message )
        {
            ReadFile();
            ProcessReceivedMessage();
        }
        FileFlushBuffers();
        DisconnectNamedPipe();
    }
}
CloseHandle( the pipe );

My client version goes like this (pseudo code):

if( WaitNamedPipe( FOREVER ) != 0 )
{
    GetParametersAndFormAMessage();
    CreateFile();
    WriteFile(); // Sends message to the pipe server
}
CloseHandle();

According to MSDN, if the server uses DisconnectNamedPipe(), the client is forced disconnected and on the next attempt of the client, they will get an error. Do you think that's the reason? If so, how do I disconnect a client without that extra error happening? Otherwise, anything I should know to make this work??? Spent a lot of hours figuring this out.

Answer

Chris Dickson picture Chris Dickson · Dec 18, 2010

You should handle communication with each client instance on a different server-side instance of the pipe, using a separate thread for each. So, when ConnectNamedPipe() returns, immediately spawn a new listener thread to wait for the next client, before processing the message from the client which just connected.

Each client will then be talking via a freshly created instance of the pipe, and you won't see the ERROR_PIPE_NOT_CONNECTED errors.

i.e. psuedo-code something like this:

Main Thread
{
    CreateListenerThread();
    WaitForQuitEvent();
}

ListenerThread
{
    ConnectNamedPipe();
    if (no error)
    {
        CreateListenerThread();
        if( PeekNamedPipe() has a message )
        {
            ReadFile();
            ProcessReceivedMessage(); // if -quit signal quit event
        }
        FileFlushBuffers();
        DisconnectNamedPipe();
        CloseHandle();
    }
    else
    {
        // handle/report error
    }
}