3

I'm trying to set a timeout to the reading operation of my named pipe.
In order to read from the named pipe, I'm using the ReadFile function.
I read that a timeout can be set for this function with the SetCommTimeouts function but when I try to use it, I get system error 1: "Incorrect function".
Here is my code (this is the client side):

m_pipe = CreateFileA(pipeName,   // pipe name 
                         GENERIC_READ |  // read and write access 
                         GENERIC_WRITE, 
                         0,              // no sharing 
                         NULL,           // default security attributes
                         OPEN_EXISTING,  // opens existing pipe 
                         0,              // default attributes 
                         NULL);          // no template file 

    if (m_pipe != INVALID_HANDLE_VALUE)
    {
            DWORD mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
            ok = SetNamedPipeHandleState(m_pipe, &mode, NULL, NULL);
            COMMTIMEOUTS cto;
            cto.ReadTotalTimeoutConstant = 1000;
            BOOL time = SetCommTimeouts(m_pipe, &cto);
    }

Am I doing something wrong or the SetCommTimeouts method is not supposed to be used with pipes? Is there any other way to get a reading timeout?

Idov
  • 5,006
  • 17
  • 69
  • 106

3 Answers3

15

If the purpose of the timeout is to not get stuck forever you may consider a call to PeekNamedPipe(...) in a timed loop. This way you can check whether there is anything to read from time to time. Alternatively PeekNamedPipe may be used to decide whether a read on the pipe is actually going to get anything before the read is performed. This way a "waiting" read can be avoided.

Arno
  • 4,994
  • 3
  • 39
  • 63
3

You cannot use SetCommTimeouts with named pipes. If you want timeouts, you will have to use Async I/O and implement the timeout yourself using CancelIo or CancelIoEx

Nik Bougalis
  • 10,495
  • 1
  • 21
  • 37
  • Could you explain, why cannot use timeouts with named pipes or give a link to a source of this knowledge? – Tomasz Dzięcielewski May 20 '14 at 09:55
  • The answer, unfortunately, is: "*because you just can't: the API doesn't allow it.*" I wish I had a better, more in-depth answer to give you, alas I don't. You may want to read [this MSDN page](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365788(v=vs.85).aspx). Bottom line: If you want "timeouts" you need to use overlapped I/O. – Nik Bougalis May 20 '14 at 16:49
  • Ok, thanks. I think about using PeekNamedPipe, but code is "under construction". – Tomasz Dzięcielewski May 21 '14 at 07:05
2

ReadFile blocks until it read requested amount of bytes or error/abort happen. Overlapped works same, i.e. it completes on same conditions. Tried to implement timeouts using CancelIoEx and figured out that it loses data. Until now see no way to implement timeouts and read only part of requested amount of bytes, or read cached data.