HasOverlappedIoCompleted()
doesn't work on asynchronous I/O begun with ReadFileEx()
and WriteFileEx()
. The code snippet at the bottom demonstrates this. In this example, ReadFileEx()
reads from a pipe that has no input, so the read will not complete. But HasOverlappedIoCompleted()
returns TRUE. If I change the call to an overlapped ReadFile()
then HasOverlappedIoCompleted()
returns FALSE as expected.
My question is: How can I find out whether an overlapped I/O request with callback has completed, without relying on the callback itself? In my application, the APC may have been queued but need not necessarily have run yet because the application may not yet have waited in an alertable state.
Thanks.
(Note GetOverlappedResult() doesn't help - it also returns TRUE.)
A bit more background: In the example I'm using ReadFileEx()
because it is easy to demonstrate the problem. In my application I am calling WriteFileEx()
repeatedly on a pipe instance. If the previous WriteFileEx()
has not yet completed I must drop the message rather than send it (I must not have more than one pending write on the same pipe instance), but if the previous WriteFileEx()
has completed then I must start the next one, even if the completion callback has not yet run.
Edit: A description of the problem scenario
- The thread enters an alertable state (with one read APC queued).
- The read APC begins: It queues a WriteFileEx() and sets a 'write pending' flag. It then queues a ReadFileEx().
- The main thread begins work (non-alertable).
- The queued read completes.
- The queued write completes (after the read).
- The main thread enters an alertable state.
- The read APC is first in the queue so runs first: It looks at the 'write pending' flag and since it is still set it drops the write. In fact though the WriteFileEx() has completed, it just hasn't called its APC yet because the ReadFileEx() completed first.
Instead of testing my custom 'write pending' flag, I want to find out from the OS whether the WriteFileEx() has actually completed, even if the APC hasn't yet run.
#include <Windows.h>
#include <stdio.h>
#include <assert.h>
VOID CALLBACK readComplete(DWORD err, DWORD bytes, LPOVERLAPPED ovlp)
{
}
int main(int argc, char *argv[])
{
HANDLE hServer;
OVERLAPPED serverOvlp = { 0 };
HANDLE hClient;
DWORD bytes;
BYTE buffer[16];
BOOL result;
hServer = CreateNamedPipe("\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
serverOvlp.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ConnectNamedPipe(hServer, &serverOvlp);
assert(GetLastError() == ERROR_IO_PENDING);
hClient = CreateFile("\\\\.\\pipe\\testpipe", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
GetOverlappedResult(hServer, &serverOvlp, &bytes, TRUE);
/* Server starts an overlapped read */
// result = ReadFile(hServer, buffer, sizeof(buffer), &bytes, &serverOvlp);
result = ReadFileEx(hServer, buffer, sizeof(buffer), &serverOvlp, readComplete);
if (HasOverlappedIoCompleted(&serverOvlp))
{
puts("Completed");
}
else
{
puts("Not completed");
}
return EXIT_SUCCESS;
}
readComplete
toReadFileEx
? – GabeReadFile
then it works as expected. What if you changereadComplete
toNULL
? Does it work as expected or not? – Gabe