Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows Named Pipe issue: Error code 233 alternates

Tags:

named-pipes

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.

like image 674
MrHuggies Avatar asked Dec 15 '10 15:12

MrHuggies


1 Answers

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
    }
}
like image 187
Chris Dickson Avatar answered Oct 25 '22 13:10

Chris Dickson