My program uses Overlapped IO for serial port communications. COMMTIMOUTS
are set to be non blocking by setting ReadIntervalTimeout = MAXDWORD. Calls
to ReadFile and WriteFile return immediately. I use WaitCommEvent and event
objects to know when data is sent and ready to read. I use
WaitForSingleObject to wait for data or timeout. When I timeout I need to
cancel the pending operations which is only the one that should still be
pending.
Documentation on CancelIo says that it should cancel any pending operations
on that thread. After calling CancelIo I call GetOverlappedResults for the
structure I passed to WaitCommEvent. GetOverlappedResults returns false and
GetLastError returns
995: "The I/O operation has been aborted because of either a thread exit or
an application request."
But leaving the function generates a stack corruption error around one of my
local variables.
Currently as a work around I manually call SetEvent to set the event in the
overlapped structure to signaled. I don't get stack corruption errors any
more but I don't know if this is the correct and safe way to do it.
Any input would be greatly appreciated.
Thanks,
jim
"Jim H" <nos...@jimsaccount.com> wrote in message
news:uwQAAEHZ...@TK2MSFTNGP11.phx.gbl...
The ERROR_OPERATION_ABORTED error code is an expected result after calling
CancelIo.
About the stack corruption issue,
you may try enable the Buffer Security Check option in your project setting
(c++ code gen) to help debug this issue.
If you still have problem on it, could you post some related code snippet
of your I/O functions?
Here is a technical article discusses Win32 Serial Communication
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/htm
l/msdn_serial.asp
You may try its sample code with some small modifications to see if the
stack corruption will occur.
Please feel free to reply this thread and let me know more about this issue
if you still have problem on this issue.
Thanks!
Best regards,
Ying-Shen Yu [MSFT]
Microsoft Community Support
Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, please remove the word "online"
before sending mail.
jim
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:%23LPyunJ...@TK2MSFTNGP12.phx.gbl...
Any ideas? Is there something special about WaitCommEvent? I have no
problems with ReadFile and WriteFile. I wish I could get away without using
WaitCommEvent, but it doesn't seem like I can.
jim
""Ying-Shen Yu[MSFT]"" <v-...@online.microsoft.com> wrote in message
news:XMDqq9LZ...@cpmsftngxa06.phx.gbl...
The structure is still required. Calling CancelIo() does not guarantee that
the operation will actually be cancelled, it may still be completed
normally. So you must wait for the operation to complete in any case. And if
the OVERLAPPED structure or any IO buffer was allocated on stack, you must
do so in the same function, or you will get exactly what you're getting,
stack corruption.
S
Thanks again,
jim
"Slava M. Usov" <stripit...@gmx.net> wrote in message
news:eorHN9OZ...@tk2msftngp13.phx.gbl...
"Jim H" <nos...@jimsaccount.com> wrote in message
news:%23bfw4zO...@TK2MSFTNGP10.phx.gbl...
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:umX26cP...@tk2msftngp13.phx.gbl...
"Jim H" <nos...@jimsaccount.com> wrote in message
news:el9NYiQZ...@tk2msftngp13.phx.gbl...
Any other suggestions?
Jim
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:e3byLnS...@tk2msftngp13.phx.gbl...
> GetOverlappedResult, as you do already.
>
> "Jim H" <nos...@jimsaccount.com> wrote in message
> news:el9NYiQZ...@tk2msftngp13.phx.gbl...
> > So how do I know when it's done?
> >
snip
"Jim H" <nos...@jimsaccount.com> wrote in message
news:eTxat8SZ...@TK2MSFTNGP10.phx.gbl...
Could you send a simple sample project to reproduce this problem to me?
I'd like to see if I could figure out some thing.
Thanks,
jim
""Ying-Shen Yu[MSFT]"" <v-...@online.microsoft.com> wrote in message
news:7BtxLcYZ...@cpmsftngxa06.phx.gbl...
1. You need to specify event handle for WriteFile OVERLAPPED. Because you
don't give it, your GetOverlappedReault doesn't make any good for lDummyOl.
2. Use PurgeComm if you really want to only cancel write.
3. CancelIo should work.
4. You may want greater timeout for write in SetCommTimeouts
5. You misuse ppnBytesWritten in GetOverlappedResult for WaitCommMask
6. Make sure to call GetOverlappedResult for all cases in returned event
mask. You fail to call it for EV_RXCHAR. Note that you lose EV_RXCHAR
notification for your read function (you won't get another until more
characters arrive).
If you need to abort the write if the real transmission takes too long, only
in this case you want to wait for TXEMPTY. Note that CancelIo won't discard
data already in TX buffer, so to abort transmit you need to call PurgeComm.
If you only want to limit time your WriteFile call takes, wait for WriteFile
event with a timeout, call PurgeComm(PURGE_TXABORT) if it times out, call
GetOverlappedResult after that in all cases.
Make sure you create events as manual-reset.
"Jim H" <nos...@jimsaccount.com> wrote in message
news:%23CO52Bb...@TK2MSFTNGP12.phx.gbl...
> Write function attached in function.cpp
>
> Thanks,
> jim
>
> "Alexander Grigoriev" <al...@earthlink.net> wrote in message
> news:%237R%23sRWZE...@TK2MSFTNGP11.phx.gbl...
1. No, I don't need to specify an event handle to WriteFile unless I plan
on waiting on that one. I do specify an event handle in the overlapped
structure I pass to WaitCommEvent and I do wait on that event handle. One
of the comm events I wait on is EV_TXEMPTY, which means the Write buffer is
empty and WriteFile has competed. That's why I don't need an event handle
for WriteFile. I pass in a dummy overlapped structure because the port was
opened with the overlapped option so an overlapped structure is required.
Event handles are not required to be passed in though. GetOverlappedResult
still gets the correct result based on the structure passed in. But I don't
use the lDummyOl from WriteFile anyway, I don't need it.
2. PurgeComm will clear and discard both read and write buffers along with
cancelling the pending IO operations. This will corrupt data for the next
read if unread data was waiting in the buffer and I will have lost those
bytes. I don't think I mentioned it but this application runs the reads in
a separate thread. CancelIo only cancels pending operations in the calling
thread so it has 2 benefits. It will not throw away data I need and it will
not cancel pending read operations that are in the other thread. Either way
I don't want to discard data form the receive or transmit buffers. If a
read times out I don't want to throw away transmit data, and if a write
times out I don't want to throw away receive data.
3. I know CancelIo() should work, but it doesn't. It cancels something
with WaitCommEvent because GetOverlappedResults will NOT block waiting for
it after a call to CancelIo. That's why I'm here.
4. I would actually prefer a timeout pf 0 since I'm using WaitCommEvent to
know when the buffer has been emptied. I changed it to 1 for testing. I
thought with a timeout of 0 WriteFile would return successful no matter what
and report 0 bytes written like ReadFile does, but it didn't.
5. You are correct, that's a typo. It never bit me because I don't
actually use the ppnBytesWritten for its value. Thanks for catching it I
changed it in my code.
6. The read thread waits on a separate event handle and uses separate local
overlapped structures. Both threads get signaled for all events and each
thread processes accordingly. Currently everything is working fine. I
manually set the event to a signaled state and that appears to get the
pending WaitCommEvent to come out. I just don't know if that's the
correct/safe way to do it. The ReadFile calls don't block at all because of
the comm timeouts. The WriteFile calls shouldn't because I know when I'm
sending data to the device, I don't know in advance when the device will be
sending data to me (one of the reasons for the read thread and non-blocking
IO). But I still don't like "shouldn't".
Technically with the device and hardware interface the writes are not going
to time out, but I need to know when they are done. The data from the reads
vary in length and structure so I don't know what I'm getting until I start
to get it. It might be a structured packet it might not. That logic is
worked out and runs fine.
Again I only sent the Write function because it is smaller and more simple
than the Read function. The logic for sending and receiving work fine. The
problem occurs if there is a timeout and I need to cancel the pending calls
so I can leave the function. My SetEvent workaround is doing the trick, but
that doesn't mean it's the right way to do it.
WaitCommEvent has some very strange behavior. Sometimes it returns an error
code of 87 (Bad parameter). I've seen a bunch of posts abot this problem.
Some say they fixed it by calling SetCommMask before each call to
WaitCommEvent. I don't like that because it causes artificial wakeups in
the different threads and just more checking for me. I tried it to see if
it worked, but it didn't help me. The strange thing is, if I ignore the
error and just start my loop over (it really only happens in the looping
read thread) it works fine the next time and everything continues to
function.
I appreciate your time and input.
Jim
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:uDZXGbcZ...@TK2MSFTNGP11.phx.gbl...
[...]
> 1. No, I don't need to specify an event handle to WriteFile unless I plan
> on waiting on that one. I do specify an event handle in the overlapped
> structure I pass to WaitCommEvent and I do wait on that event handle. One
> of the comm events I wait on is EV_TXEMPTY, which means the Write buffer
> is empty and WriteFile has competed. That's why I don't need an event
> handle for WriteFile. I pass in a dummy overlapped structure because the
> port was opened with the overlapped option so an overlapped structure is
> required. Event handles are not required to be passed in though.
Becuase lDummyOl does not have an event, GetOverlappedResult() will wait for
the file handle itself to become signalled. And the latter becomes signalled
when the _first_ GetOverlappedResult() returns. Which means the second
GetOverlappedResult() does not wait at all.
> GetOverlappedResult still gets the correct result based on the structure
> passed in.
Which one?
[...]
> 2. PurgeComm will clear and discard both read and write buffers along
> with cancelling the pending IO operations.
That depends on its flags. If it is only PURGE_TXABORT, it will only cancel
all outstanding writes.
S
> > GetOverlappedResult still gets the correct result based on the structure
> > passed in.
>
> Which one?
When I call GetOverlappedResults passing in &lOverlapped. During normal
use. After calling CancelIo I call GetOverlappedResults on both the
WriteFile and WaitCommEvent. GetOverlappedResults returns TRUE for the
WriteFile overlapped structure and false for the WaitCommEvent structure if
I call CancelIo.
>
> [...]
>
> > 2. PurgeComm will clear and discard both read and write buffers along
> > with cancelling the pending IO operations.
>
> That depends on its flags. If it is only PURGE_TXABORT, it will only
cancel
> all outstanding writes.
True, I forgot about that. Either way I need to safely cancel my
WaitCommEvent call. Is manually setting the event using SetEvent a safe way
to do that>
>
> S
>
>
"Jim H" <nos...@jimsaccount.com> wrote in message
news:%233r5GKr...@TK2MSFTNGP09.phx.gbl...
[...]
> I don't call GetOverlappedResults to wait on the RaedFile and WriteFile
> calls. I call GetOverlappedResults on the WaitCommEvents call. ReadFile
> never causes an overlapped operation because of the comm timeouts.
There are two pending IO requests when you call CancelIo(): the write
request and the "wait comm" request. You must wait for both of them to
complete before you can return from your function. That means you must have
two GetOverlappedResults() and you must have a separate event handle for
each one. And you _must_ call GetOverlappedResults() for _anything_ that
returns ERROR_STATUS_PENDING, timeouts or not.
[...]
> Is manually setting the event using SetEvent a safe way to do that
No. You must use CancelIo() or PurgeComm() and wait for _both_ requests to
complete. Which implies two event objects.
S
How do I wait for that last request to complete if GteOverlappedResults
won't block waiting for it and reborts the call was aborted?
"Slava M. Usov" <stripit...@gmx.net> wrote in message
news:es2gqC2...@TK2MSFTNGP10.phx.gbl...
Thanks for the help,
jim
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:%23Mt4CWw...@tk2msftngp13.phx.gbl...
Why don't you stop arguing and try the advice of two (2) MS MVPs?
Is creating an extra event handle worth 4 days lost for discussing such a
little problem?
You don't need to supply an event in OVERLAPPED only in two cases:
1. The handle is open in non-overlapped mode. In this case you can supply
OVERLAPPED structure to perform file I/O from an arbitrary file pointer
position (specified in OVERLAPPED fields).
2. You're using I/O completion ports.
"Jim H" <nos...@jimsaccount.com> wrote in message
news:%23w%23yZjCa...@tk2msftngp13.phx.gbl...
[...]
> How do I wait for that last request to complete if GteOverlappedResults
> won't block waiting for it and reborts the call was aborted?
You have been told "how". By having a separate event just for that. Sorry, I
am not going to repeat that again.
S
I'm not trying to be stubborn or argumentative. The event I pass in with
the overlapped structure to WaitCommEvent is for WaitCommEvent only. And
there is a separate event I use for the WaitCommEvent I have in the read
thread. I don't pass in an event with the WriteFile or ReadFile call. This
is on the advice of another MS MVP I got else where (not this board, some
web site). And it made sense to me. He/she said to use WaitCommEvent
instead of passing in an event to ReadFile and WriteFile. That's what
WaitCommEvent is for. With the read interval of the comm timeout structure
set to MAXDWORD the reads and writes should not wait. They should complete
successfully and I'm supposed to check the bytes written/read. According to
the documentation passing in an overlapped structure does not guarantee an
overlapped operation. If the function returns TRUE there is no overlapped
operation.
I have done what this other person suggested in how I set it up. I do have
a separate event for WaitCommEvent like you guys here have suggested. It's
been like that from the beginning. Is the other MVP wrong in suggesting
that I NOT pass in an event object with the overlapped structure when I call
ReadFile and WriteFile? Even if I never need to wait on it?
Reads always return successfully (no overlapped operation) even if 0 bytes
were read so there is no overlapped operation. If 0 bytes are read after
the ReadFile call I call WaitCommEvent which does cause an overlapped
operation and wait until data has arrived before I call read again by
waiting on the event object passed into WaitCommEvent. I use
GetOverlappedResults to make sure it's an EV_RXCHAR before I call read
again.
Writes may cause an overlapped operation but I always call WaitCommEvent and
check for EV_TXEMPTY to know when the write completes. I call
GetOverlappedResults on the structure I passed into WriteFile also before
leaving the write function. If the tx buffer is empty the write must have
completed.
If someone could explain why I do or do not need them that would be great.
The person I listened to initially expained why I they didn't use them.
People here keep saying to use them but don't say why. The MSDN
documentation says they are not required and that you can wait on the file
handle. From the MSDN:
If the hEvent member of the OVERLAPPED structure is NULL, the system uses
the state of the hFile handle to signal when the operation has been
completed. Use of file, named pipe, or communications-device handles for
this purpose is discouraged. It is safer to use an event object because of
the confusion that can occur when multiple simultaneous overlapped
operations are performed on the same file, named pipe, or communications
device. In this situation, there is no way to know which operation caused
the object's state to be signaled.
The way the other person explained it to me made sense because I never wait
on the file handle or anything from the WriteFile or ReadFile operations. I
wait on the event object used in the call to WaitCommEvent "IF" WriteFile or
ReadFile returned false with an ERROR_IO_PENDING code. Is this other MVP
wrong? If so then fine I'll rewrite my code again.
I am adding in the extra event objects just to combine the advice of the
different MVPs.
Do I need to call SetCommMask after every call to WaitCommEvent? The
documentation does not say this is required, but the code runs differently
when I do. (Even without the read thread running)
"Slava M. Usov" <stripit...@gmx.net> wrote in message
news:OZVLWBDa...@TK2MSFTNGP11.phx.gbl...
I am adding in the extra event objects just to combine the advice of the
different MVPs.
Do I need to call SetCommMask after every call to WaitCommEvent? The
documentation does not say this is required, but the code runs differently
when I do. (Even without the read thread running)
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:OdQqivCa...@tk2msftngp13.phx.gbl...
A file handle is "signalled" when an I/O operation completes, and is "reset"
when another operation starts. For overlapped I/O, with several operations
in parallel, you can't know which operation caused the handle to become
"signalled". So any wait on an OVERLAPPED without an event handle becomes
meaningless and dangerous for your program's logic.
One common approach to using ReadFile without timeouts is to issue
WaitCommEvent for EV_RXCHAR, then get number if available characters in
COMSTAT::cbInQueue by calling ClearCommError, then request read for exact
number of bytes. Even in this case you should not assume ReadFile not
returning ERROR_IO_PENDING. It _may_ return FALSE+ERROR_IO_PENDING, even
though the operation is actually completed immediately.
WriteFile will never return immediately, if it cannot accept all data, no
matter where MAXDWORD is set. You have to control it with finite timeouts.
See COMMTIMEOUTS description.
Note that if you cancel WriteFile prematurely, it may break your transmit
protocols. You may need to think about resynchronizing your data stream.
The bottom line:
You may omit the event handle in OVERLAPPED, but it will bring you big pain
in the bottom. You will have to serialize all your I/O then. If you issue
requests from multiple threads, don't even think about NULL event handle.
"Jim H" <nos...@jimsaccount.com> wrote in message
news:ewTS1%23EaEH...@TK2MSFTNGP09.phx.gbl...
I like the approach of using an event object in the Write/ReadFile calls and
I think I'm going to try using those event objects and get rid of the
WaitCommEvent calls. I did not know I could do this. I thought with serial
devices WaitCommEvent was required to do overlapped I/O calls. I should be
able to use use the events passed into ReadFile and WriteFile the same way
right? WaitCommEvent has given me so many headaches I'd love to get rid of
it. Once every 100 or so calls in the same loop WaitCommEvent returns an
87: bad parameter, error code. I have yet to figure out why, but if I
ignore the error and just go back to the start of the loop and call it again
it works fine. I'm not dealing with a modem or flow control (DTS, CTS,
etc...) which is more along the lines of what WaitCommEvent is meant for
right? Or should I continue to use WaitCommEvent? All I really needed to
do was provide some kind of timed read and write capability. In actuallity
just a timed read since, with this device, the writes won't timeout unless
there was a hardware failure. I was asked to provide the application with a
read timeout that would return after so much time if no data was received.
It is possible that I won't get my expected results depending on the state
of the device the hardware interface is connected to and the app used to
hang once data stopped coming in. The COMMTIMEOUTS don't start until the
first byte is received unless read interval is set to MAXDWORD in which case
it will not wait at all.
Thanks again for your time and patience. I work better when people explain
why rather than how. I do appreciated it.
jim
"Alexander Grigoriev" <al...@earthlink.net> wrote in message
news:e9P4ZOJa...@TK2MSFTNGP10.phx.gbl...
[...]
> People here keep saying to use them but don't say why. The MSDN
> documentation says they are not required and that you can wait on the file
> handle. From the MSDN:
> If the hEvent member of the OVERLAPPED structure is NULL, the system uses
> the state of the hFile handle to signal when the operation has been
> completed. Use of file, named pipe, or communications-device handles for
> this purpose is discouraged. It is safer to use an event object because of
> the confusion that can occur when multiple simultaneous overlapped
> operations are performed on the same file, named pipe, or communications
> device. In this situation, there is no way to know which operation caused
> the object's state to be signaled.
That thing explains it all. It says "confusion" and "multiple simultaneous
overlapped operations". These two items were exactly what you had. I
explained that same thing on the 9th of July:
[quote]
Becuase lDummyOl does not have an event, GetOverlappedResult() will wait for
the file handle itself to become signalled. And the latter becomes signalled
when the _first_ GetOverlappedResult() returns. Which means the second
GetOverlappedResult() does not wait at all.
[end quote]
> The way the other person explained it to me made sense because I never
> wait on the file handle or anything from the WriteFile or ReadFile
> operations. I wait on the event object used in the call to WaitCommEvent
> IF WriteFile or ReadFile returned false with an ERROR_IO_PENDING code. Is
> this other MVP wrong?
In the context of having two asynchronous IO requests that was definitely
wrong. You must always be able to sense the completion of each one to
reclaim resources allocated for it, and it is not possible with one event.
Or you should avoid the whole issue by not having multiple async requests on
one handle.
> Do I need to call SetCommMask after every call to WaitCommEvent? The
> documentation does not say this is required, but the code runs differently
> when I do. (Even without the read thread running)
That probably happens because of the incorrect cancellation. SetCommMask()
will itself cancel all waits [which may be another source of corruption,
BTW].
[...]
> I like the approach of using an event object in the Write/ReadFile calls
> and I think I'm going to try using those event objects and get rid of the
> WaitCommEvent calls. I did not know I could do this. I thought with
> serial devices WaitCommEvent was required to do overlapped I/O calls. I
> should be able to use use the events passed into ReadFile and WriteFile
> the same way right?
If you do not need to sense those funny states, then ReadFile() and
WriteFile() are all that you need.
[...]
> Once every 100 or so calls in the same loop WaitCommEvent returns an
> 87: bad parameter, error code.
That may happen because of the incorrect cancellation again. WaitCommEvent()
will fail with that status when there is another WaitCommEvent() in
progress.
S
As an add in... The error code 87 happened without any calls to CancelIo.
But since you say something else can cause the wait to "wake up" does it
makes sense that I might get that if the operation did not actually
complete, or GetOverlappedResults was not called on it yet? I'm still not
sure how the low level process flows.
Thanks again,
jim
"Slava M. Usov" <stripit...@gmx.net> wrote in message
news:OaUlfcOa...@tk2msftngp13.phx.gbl...
[...]
> As an add in... The error code 87 happened without any calls to CancelIo.
> But since you say something else can cause the wait to "wake up" does it
> makes sense that I might get that if the operation did not actually
> complete, or GetOverlappedResults was not called on it yet? I'm still not
> sure how the low level process flows.
Without CancelIo() and without SetCommMask() your previous WaitCommEvent()
request may still be pending when you call WaitCommEvent(), and you cannot
have more than one WaitCommEvent(); so WaitCommEvent() is rejected with
error 87.
The same thing may happen even if you do call CancelIo() but do not call
GetOverlappedResult(); the window is _much_ smaller, though.
S