Asynchronous read from a pipe does not detect when the message is send after a first timeout read

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hi
I would like to open in message mode a communication pipe with a client using asynchronous IO and then wait for message reception on this pipe. The wait is done, after opening the connection, with ReadFile() in asynchronous mode. However, I have noticed
that if I am doing a first ReadFile() with timeout, then a WriteFile() on the other end of the pipe, the ReadFile() always fails with timeout without being able to detect the message. Below is a code snippet:
<span style="color:#333333; font-family:Segoe UI,Lucida Grande,Verdana,Arial,Helvetica,sans-serif; font-size:x-small <span style="line-height:16px
<div style="color:Black;background-color:White; <pre>
#define PIPE_BUFFER_SIZE 1024
#define PIPE_NAME_PREFIX "\\.\pipe\"
#define PIPE_TIMEOUT 5000
<span style="color:Green; //#define REMOVE_1ST_READ

<span style="color:Blue; int main(<span style="color:Blue; void)
{
HANDLE _hPipe[] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
DWORD _nBytes = 0;
TCHAR _szFullPipeName[PIPE_BUFFER_SIZE];
TCHAR _szPipeName[] = _T(<span style="color:#A31515; "common");
OVERLAPPED _ovRead;
OVERLAPPED _ovWrite;
<span style="color:Blue; int _rc, _ec;
BYTE _pBuffer[3];
<span style="color:Blue; const DWORD _nBufferLen = 3;

<span style="color:Green; /* create the full name of the pipe */
<span style="color:Blue; if (0 != wcscpy_s(_szFullPipeName, PIPE_BUFFER_SIZE, _T(PIPE_NAME_PREFIX)))
{
printf(<span style="color:#A31515; "error in wcscpy_sn");
<span style="color:Blue; return EXIT_FAILURE;
}
<span style="color:Blue; if (0 != wcscat_s(_szFullPipeName, PIPE_BUFFER_SIZE, _szPipeName))
{
printf(<span style="color:#A31515; "error in wcscat_sn");
<span style="color:Blue; return EXIT_FAILURE;
}

_hPipe[0] = CreateNamedPipe(
_szFullPipeName, <span style="color:Green; /* name */
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, <span style="color:Green; /* open mode */
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, <span style="color:Green; /* pipe mode */
1, <span style="color:Green; /* max number of instances */
PIPE_BUFFER_SIZE, <span style="color:Green; /* output buffer size */
PIPE_BUFFER_SIZE, <span style="color:Green; /* input buffer size */
PIPE_TIMEOUT, <span style="color:Green; /* wait timeout */
NULL <span style="color:Green; /* security attributes */
);
<span style="color:Blue; if (INVALID_HANDLE_VALUE == _hPipe[0])
{
printf(<span style="color:#A31515; "error in CreateNamedPipen");
<span style="color:Blue; return EXIT_FAILURE;
}

<span style="color:Green; /* open connection client side */
_hPipe[1] = CreateFile(
_szFullPipeName,<span style="color:Green; /* pipe name */
GENERIC_READ | GENERIC_WRITE, <span style="color:Green; /* read and write access */
0, <span style="color:Green; /* no sharing */
NULL, <span style="color:Green; /* default security attributes */
OPEN_EXISTING, <span style="color:Green; /* opens existing pipe */
FILE_FLAG_OVERLAPPED,<span style="color:Green; /* default attributes */
NULL); <span style="color:Green; /* no template file */
<span style="color:Blue; if (INVALID_HANDLE_VALUE == _hPipe[1])
{
printf(<span style="color:#A31515; "error in CreateFilen");
<span style="color:Blue; return EXIT_FAILURE;
}

<span style="color:Green; /* open connection server side */
memset(&_ovRead, 0, <span style="color:Blue; sizeof(_ovRead));
<span style="color:Blue; if (INVALID_HANDLE_VALUE == (_ovRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
{
printf(<span style="color:#A31515; "error in CreateEventn");
<span style="color:Blue; return EXIT_FAILURE;
}
ConnectNamedPipe(_hPipe[0], &_ovRead);
<span style="color:Blue; if (ERROR_IO_PENDING == (_rc = GetLastError()))
{
<span style="color:Green; //ouverture asynchrone: retour après attente
_ec = WaitForSingleObject(_ovRead.hEvent, 100);
<span style="color:Blue; switch(_ec)
{
<span style="color:Blue; case WAIT_OBJECT_0:
_rc = EXIT_SUCCESS;
<span style="color:Blue; break;
<span style="color:Blue; case WAIT_TIMEOUT:
printf (<span style="color:#A31515; "time out 1st readn");
_rc = EXIT_FAILURE;<span style="color:Green; /* timeout is failure */
<span style="color:Blue; break;
<span style="color:Blue; default:
_rc = EXIT_FAILURE;
}
}
<span style="color:Blue; if (EXIT_SUCCESS != _rc && ERROR_PIPE_CONNECTED != _rc)
{
printf(<span style="color:#A31515; "error when opening the connection server siden");
<span style="color:Blue; return EXIT_FAILURE;
}
printf(<span style="color:#A31515; "connection establishedn");

<span style="color:Green; /* server reads, but read times out */
#ifndef REMOVE_1ST_READ
printf(<span style="color:#A31515; "dummy readn");
memset(&_ovRead, 0, <span style="color:Blue; sizeof(_ovRead));
<span style="color:Blue; if (INVALID_HANDLE_VALUE == (_ovRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
{
printf(<span style="color:#A31515; "error in CreateEventn");
<span style="color:Blue; return EXIT_FAILURE;
}
memset(_pBuffer, 0, _nBufferLen);
<span style="color:Blue; if (0 == ReadFile(_hPipe[0], _pBuffer, _nBufferLen, &_nBytes, &_ovRead))
{
<span style="color:Blue; if (ERROR_IO_PENDING == (_ec = GetLastError()))
{
<span style="color:Green; /* attente de la fin de la lecture */
_ec = WaitForSingleObject(_ovRead.hEvent, 100);
<span style="color:Blue; switch(_ec)
{
<span style="color:Blue; case WAIT_OBJECT_0:
_rc = (0 != GetOverlappedResult(_hPipe[0], &_ovRead, &_nBytes, TRUE))?EXIT_SUCCESS:EXIT_FAILURE;
<span style="color:Blue; break;
<span style="color:Blue; case WAIT_TIMEOUT:
printf (<span style="color:#A31515; "time out 1st readn");
_rc = EXIT_SUCCESS;<span style="color:Green; /* timeout is not a failure */
<span style="color:Blue; break;
<span style="color:Blue; default:
_rc = EXIT_FAILURE;
}
}
<span style="color:Blue; if (EXIT_SUCCESS != _rc)
{
<span style="color:Green; /* lecteure terminée ou erreur */
printf(<span style="color:#A31515; "error in ReadFilen");
<span style="color:Blue; return EXIT_FAILURE;
}
}
#endif

<span style="color:Green; /* client writes to pipe */
memset(&_ovWrite, 0, <span style="color:Blue; sizeof(_ovWrite));
<span style="color:Blue; if (INVALID_HANDLE_VALUE == (_ovWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
{
printf(<span style="color:#A31515; "error in CreateEventn");
<span style="color:Blue; return EXIT_FAILURE;
}
memset(_pBuffer, a, _nBufferLen);
<span style="color:Blue; if (0 == WriteFile(_hPipe[1], _pBuffer, _nBufferLen, &_nBytes, &_ovWrite))
{
<span style="color:Blue; if (ERROR_IO_PENDING == (_rc = GetLastError()))
{
_ec = WaitForSingleObject(_ovWrite.hEvent, INFINITE);
<span style="color:Blue; switch(_ec)
{
<span style="color:Blue; case WAIT_OBJECT_0:
_rc = (0 != GetOverlappedResult(_hPipe[1], &_ovWrite, &_nBytes, TRUE))?EXIT_SUCCESS:EXIT_FAILURE;
<span style="color:Blue; break;
<span style="color:Blue; case WAIT_TIMEOUT:
printf (<span style="color:#A31515; "time out writen");
_rc = EXIT_SUCCESS;
<span style="color:Blue; break;
<span style="color:Blue; default:
_rc = EXIT_FAILURE;
}
}
<span style="color:Blue; if (EXIT_SUCCESS != _rc)
{
printf(<span style="color:#A31515; "error in WriteFilen");
<span style="color:Blue; return EXIT_FAILURE;
}
}
printf(<span style="color:#A31515; "message has been sendn");

<span style="color:Green; /* server reads again */
memset(&_ovRead, 0, <span style="color:Blue; sizeof(_ovRead));
<span style="color:Blue; if (INVALID_HANDLE_VALUE == (_ovRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL)))
{
printf(<span style="color:#A31515; "error in CreateEventn");
<span style="color:Blue; return EXIT_FAILURE;
}
memset(_pBuffer, 0, _nBufferLen);
<span style="color:Blue; if (0 == ReadFile(_hPipe[0], _pBuffer, _nBufferLen, &_nBytes, &_ovRead))
{
<span style="color:Blue; if (ERROR_IO_PENDING == (_ec = GetLastError()))
{
<span style="color:Green; /* attente de la fin de la lecture */
_ec = WaitForSingleObject(_ovRead.hEvent, 100);
<span style="color:Blue; switch(_ec)
{
<span style="color:Blue; case WAIT_OBJECT_0:
_rc = (0 != GetOverlappedResult(_hPipe[0], &_ovRead, &_nBytes, TRUE))?EXIT_SUCCESS:EXIT_FAILURE;
<span style="color:Blue; break;
<span style="color:Blue; case WAIT_TIMEOUT:
printf (<span style="color:#A31515; "time out 2nd readn");
_rc = EXIT_SUCCESS;
<span style="color:Blue; break;
<span style="color:Blue; default:
_rc = EXIT_FAILURE;
}
}
<span style="color:Blue; if (EXIT_SUCCESS != _rc)
{
<span style="color:Green; /* lecteure terminée ou erreur */
printf(<span style="color:#A31515; "error in ReadFilen");
<span style="color:Blue; return EXIT_FAILURE;
}
}

CloseHandle(_hPipe[0]);
CloseHandle(_hPipe[1]);
<span style="color:Blue; if (_nBufferLen == _nBytes)
{
printf(<span style="color:#A31515; "%c%c%cn", _pBuffer[0], _pBuffer[1], _pBuffer[2]);
printf(<span style="color:#A31515; "SUCCESSn");
} <span style="color:Blue; else
{
printf(<span style="color:#A31515; "FAILUREn");
}
<span style="color:Blue; return EXIT_SUCCESS;
}
[/code]
<br/>
<br/>

<hr class="sig bogdan

View the full article
 
Back
Top