There is one case where you STILL have to wait for the completion before
assuming that the operation is complete, even when you receive a TRUE
(for Win32) or STATUS_SUCCESS (for native) return code. That is when
you have the file handle bound to an I/O completion port. If that is
the case, then the completion status will always be queued to the
completion port.
There is a way to inhibit that, per-call, though. I think you set the
lowest bit of the Overlapped.Event handle.
Yeah, if you need to mix calls on a single HANDLE, emulating sync
behavior with an event isn’t a bad way to do it. You might even be
better off using APC completions and SleepEx (INFINITE, TRUE), although
that takes a little more footwork.
– arlie
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
Sent: Thursday, September 25, 2003 1:24 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] RE: Waiting for overlapped IO result
Well, Arlie, I know it all. I use overlapped IO for years at both driver
and application side. The code isn’t mine, it was copied directly from
DDK docs. My question was different: why it is written the way which
doesn’t make sense or if it does make sense to anybody. Below I copy
whole code fragment from DDK. It violates at least your last point as it
doesn’t wait for async result. Unfortunately, it seems as complete
sample and was used as such by somebody who wrote the old code I work on
now. The result was hard-to-find stack overwrite.
As for sync versus async, you’re right in principle but situation can be
more complicated. In this case the device has to be opened for
overlapped access because it used for both async read/write and IOCTLs
which are handled synchronously. I guess it is better to emulate sync
behaviour for IOCTLs than open two handles for one device. When device
is opened for overlapped access, overlapped structure can’t be removed
according to Platform SDK:
If hDevice was opened with the FILE_FLAG_OVERLAPPED flag, lpOverlapped
must point to a valid OVERLAPPED structure. In this case, the operation
is performed as an overlapped (asynchronous) operation. If the device
was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the
function fails in unpredictable ways.
DDK code:
DWORD cbRet;
BOOL bRet;
IO_BLOCK IoBlock;
OVERLAPPED overlapped;
BOOL bRet ;
IoBlock.uOffset = (BYTE)byOffset;
IoBlock.uLength = (BYTE)byNbOfReg;
IoBlock.pbyData = pbyData;
memset(&overlapped, 0, sizeof(OVERLAPPED));
overlapped.hEvent = CreateEvent(
NULL, // pointer to security attributes,
// WIN95 ignores this parameter
FALSE, // automatic reset
FALSE, // initialize to not signaled
NULL); // pointer to the event-object name
bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);
if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}
CloseHandle(overlapped.hEvent);
Best regards,
Michal Vodicka
STMicroelectronics Design and Application s.r.o. [michal.vodicka@st.com,
http:://www.st.com]
From: xxxxx@sublinear.org[SMTP:xxxxx@sublinear.org]
Reply To: xxxxx@lists.osr.com
Sent: Thursday, September 25, 2003 5:40 AM
To: xxxxx@lists.osr.com
Subject: [ntdev] RE: Waiting for overlapped IO result
You should either…
* Use synchronous I/O. Remove the overlapped structure, and invoke
the I/O control synchronously.
* Use asynchronous I/O. There are exhaustive docs on how async I/O
works. If you want for the event immediately after DeviceIoControl,
you’re just emulating synchronous behavior. Either do it
synchronously or do it asynchronously.
You should NOT…
* Issue async operations, but not record the fact that you did so.
Not tracking pending I/O requests can (and usually does) lead to
corrupted stacks, corrupted heaps, leaked memory, or all of the above.
* Touch memory that is the subject of a pending I/O request.
There are exhaustive docs on how to do all of this correctly. Read
the SDK docs on async/overlapped I/O, and abide by these absolutely
carved-in-stone rules when it comes to async I/O:
* Keep track of operations you have issued. Use reference counts,
linked lists, whatever it takes.
* Never, ever touch memory that has been handed to the kernel, while
the kernel is busy reading/writing it.
* Never mangle the contents of an OVERLAPPED structure while an I/O
request is pending.
* ALWAYS make sure that you properly wait for I/O operations to
complete before considering an object closed. Either cancel the
request, or close the handle (which implicitly cancels all open
requests on the handle), and then wait for the completions. How you
wait for them depends on which completion mechanism (APC, I/O
completion port, event,
etc.) that you are using. But you MUST do this, or you WILL corrupt
memory, and usually under the most difficult-to-debug scenarios
(strange
access patterns, heavy system/app load, etc.)
– arlie
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Michal Vodicka
Sent: Wednesday, September 24, 2003 10:41 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Waiting for overlapped IO result
Below piece of code is copied from the latest DDK docs (relevant part
only). I don’t see any reason why to wait for overlapped event when
bRet is TRUE. DeviceIoControl returned synchronously so overlapped
event should be already signaled and there is no need to wait. Is it
correct assumption or am I too tired and missing something obvious?
Yes, I know the call is benign and can’t cause any problem; just
unnecessary and makes code confusing. I’m just trying to fix old code
made by coworkers who copied there samples as-is and wonder why it was
written this way. The most confusing thing is there is no wait when
bRet is FALSE and
GetLastError() returns ERROR_IO_PENDING which can lead (and did) to
later stack corruption. Well, it is another story, I’ll file bug
report later.
bRet = DeviceIoControl( DeviceHandle,
(DWORD) IOCTL_READ_REGISTERS,
(PVOID)&IoBlock,
(DWORD)sizeof(IO_BLOCK),
(PVOID)pbyData,
(DWORD)byNbOfReg*sizeof(BYTE),
&cbRet,
&overlapped);
if( bRet == TRUE )
{
WaitForSingleObject(overlapped.hEvent, INFINITE);
// we do not the test, the result is zero
}
Best regards,
Michal Vodicka
STMicroelectronics Design and Application s.r.o.
[michal.vodicka@st.com, http:://www.st.com]
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: xxxxx@sublinear.org To
unsubscribe send a blank email to xxxxx@lists.osr.com
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: michal.vodicka@st.com To
unsubscribe send a blank email to xxxxx@lists.osr.com
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: xxxxx@sublinear.org To
unsubscribe send a blank email to xxxxx@lists.osr.com