Can I send synchronous I/O on an asynchronous (OVERLAPPED) handle?


The short answer isthat you can’t ;). Once you have opened a HANDLE by
specifying FILE_FLAG_OVERLAPPED, you must provide an OVERLAPPED structure pointer to
any HANDLE based API that requires it. If you don’t provide the pointer, the
results are undefined. This is spelled out in the docs and I don’t see this
mistake being made all that often.

But what about the hEvent field in OVERLAPPED in the structure? Do you
always have to allocate an event HANDLE? One problem with always have to allocate
the event HANDLE is that it is yet another point of failure, yet another code
path that you have to test. Surprisingly (to me at least), the answer is no. You
don’t have to allocate the hEvent, but there are a couple of caveats. First,
you must set the field to NULL. Second, you must now poll for the results by
calling GetOverlappedResults() instead of doing
a more efficient wait by calling WaitForSingleObject().


Comments (2)

  1. Foolhardy says:

    It’s not necessary to poll for IO completion; you can wait directly on the file handle, at least according to

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndevice/html/Locks_Sync.asp

    under "Threads, Processes, and Files"

    "A file I/O operation (a single IRP) is complete when the operating system signals an internal event that is embedded in the file object. Every file object has such an embedded event. The event is a synchronization (auto-reset) event; that is, the event is reset as soon as a waiting thread is notified. Applications and file system drivers that implement asynchronous I/O can wait on the file event to find out when the I/O operation completes."

    It’d be nice to have more documentation about this, or how IoCompletion objects are signalled when they have queued items.

  2. doronh says:

    Cool, didn’t reallize that one.  I should have though if I thought about the fact that PFILE_OBJECT is a dispatcher object.  Good to know (this qualified as the new thing I learned today 😉 ).  

    The one issue with waiting on the file object is if there are multiple pending I/Os (which could be from any number of threads) on the file handle and your wait is satisfied, you still have to call GetOverlappedResult() to see if the I/O you are interested in actually completed, otherwise you have to rewait on the handle.

    There is another race as well that could lead to you waiting forever or for a very long time.  The event on the file handle is an auto reset event which means that if

    1) another thread waited on the handle

    2) the other thread was woken up for your I/O completing

    3) and your I/O was the last I/O on the thread

    your thread will never wake

    if you replace 3) with

    3) and there other pending I/O but they do not complete for a very long time/forever.

    your thread will now wake up only when the remaining i/o completes.  the, of course, assumes that you have an INFINITE wait on the handle w/out a timeout.

    d