Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is an overlapped I/O alternative to WaitNamedPipe?

The WaitNamedPipe function allows a pipe client application to synchronously wait for an available connection on a named pipe server. You then call CreateFile to open the pipe as a client. Pseudocode:

// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
    if (WaitNamedPipe says connection is ready) {
        hPipe = CreateFile(...);
        if (hPipe ok or last error is NOT pipe busy) {
            break; // hPipe is valid or last error is set
        }
    } else {
        break; // WaitNamedPipe failed
    }
}

The problem is that these are all blocking, synchronous calls. What is a good way to do this asynchronously? I can't seem to find an API that uses overlapped I/O to do this, for example. For example, for pipe servers the ConnectNamedPipe function provides an lpOverlapped parameters allowing for a server to asynchronously wait for a client. The pipe server can then call WaitForMultipleObjects and wait for the I/O operation to complete, or any other event to be signaled (for example, an event signaling the thread to cancel pending I/O and terminate).

The only way I can think of is to call WaitNamedPipe in a loop with a short, finite timeout and check other signals if it times out. Alternatively, in a loop call CreateFile, check other signals, and then call Sleep with a short delay (or WaitNamedPipe). For example:

HANDLE hPipe;
while (true) {
    hPipe = CreateFile(...);
    if (hPipe not valid and pipe is busy) {
        // sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
        Sleep(100);
        // TODO: check other signals here to see if we should abort I/O
    } else
        break;
}

But this method stinks to high heaven in my opinion. If a pipe isn't available for awhile, the thread continues to run - sucking up CPU, using power, requiring memory pages to remain in RAM, etc. In my mind, a thread that relies on Sleep or short timeouts does not perform well and is a sign of sloppy multi-threaded programming.

But what's the alternative in this case?

like image 893
James Johnston Avatar asked Mar 26 '12 19:03

James Johnston


2 Answers

WaitNamedPipe is completely useless, and will just use all the cpu if you specify a timeout and there's no server waiting for it.

Just call CreateFile over and over with a Sleep like you're doing, and move it to other threads as you see appropriate. There is no API alternative.

The only "benefit" WaitNamedPipe provides is if you want to know if you can connect to a named pipe but you explicitly don't want to actually open a connection. It's junk.

If you really want to be thorough, your only options are

  • Ensure that whatever program is opening the named pipe is always calling CreateNamedPipe again immediately after it's named pipe is connected to.
  • Have your program actually check if that program is running.
  • If your intent is really not to have additional connections, still call CreateNamedPipe, and when someone connects, tell them to go away until they're waited a given amount of time, the close the pipe.
like image 88
fcrick Avatar answered Nov 08 '22 20:11

fcrick


Why can't the server just create more pipes? The performance hit in the scenario you describe isn't a problem if it is rare.

I.e. if there are usually enough pipes to go round what does it matter if you use CreateFile/Sleep instead of WaitForMultipleObjects? The performance hit will not matter.

I also have to question the need for overlapped IO in a client. How many servers is it communicating with at a time? If the answer is less than, say, 10 you could reasonably create a thread per connection.

Basically I am saying I think the reason there is no overlapped WaitforNamedPipe is because there is no reasonable use-case which requires it.

like image 36
Ben Avatar answered Nov 08 '22 20:11

Ben