Breaking ReadFile() blocking - Named Pipe (Windows API)

Mike Trader picture Mike Trader · Feb 27, 2009 · Viewed 24.6k times · Source

To simplify, this is a situation where a NamedPipe SERVER is waiting for a NamedPipe CLIENT to write to the pipe (using WriteFile())

The Windows API that is blocking is ReadFile()

The Server has created the synchronous pipe (no overlapped I/O) with blocking enabled

The client has connected, and now the server is waiting for some data.

In the normal flow of things, the client sends some data and the server processes it and then returns to ReadFile() to wait for the next chunk of data.

Meanwhile an event occurs (user input for example) and the NamedPipe SERVER must now execute some other code, which it cannot do while the ReadFile() is blocking.

At this point I need to mention that the NamedPipe Client is not my application, so I have no control over it. I cannot make it send a few bytes to unblock the server. It is just going to sit there and send no data. Since I do not have control of the Client implementation I cannot change anything on that end.

One solution would be to create a separate thread in which all ReadFile() operations are performed. That way when the event occurs, I can just process the code. The problem with that, is that the event also requires a separate thread, so now I have two additional threads for each instance of this server. Since this needs to be scalable, this is undesirable.

From another thread I have tried calling

 DisconnectNamedPipe()

and

 CloseHandle()

they both will not return (until the client writes to the pipe.)

I cannot connect to the same pipe and write a few bytes because:

"All instances of a named pipe share the same pipe name, but each instance has its own buffers and handles, and provides a separate conduit for client/server communication."

http://msdn.microsoft.com/en-us/library/aa365590.aspx

I need a way to fake it out, So the $64k dollar question is:

How can I break the blocking of ReadFile()?

Answer

Artkov picture Artkov · Aug 4, 2009

Try this before ReadFile :

BOOL WINAPI PeekNamedPipe(
  __in       HANDLE hNamedPipe,
  __out_opt  LPVOID lpBuffer,
  __in       DWORD nBufferSize,
  __out_opt  LPDWORD lpBytesRead,
  __out_opt  LPDWORD lpTotalBytesAvail,
  __out_opt  LPDWORD lpBytesLeftThisMessage
);

if(TotalBytesAvail > 0)
  ReadFile(....);

-AV-