Flush() does not always register a cleared write


I have been having some problems where calling Flush() does not always return when it should. It appears that either the EV_TXEMPTY event flag is not getting populated, or something is clearing it before it can be recorded.

I have submitted a patch that works well for my purposes, but changes the semantic meaning of a Flush() from waiting until the EV_TXEMPTY flag is registered to instead waiting until the SerialPortStream write buffer has been completely written to the serial port. I had assumed that the ProcessWrite only occurs after the serial port has actually accepted the data, but I don't know this for certain.


perturbare wrote Aug 26, 2015 at 6:59 PM

If Microsoft's sample serial driver is a good guide for the behavior of their production driver, I believe the EV_TXEMPTY event will not fire in the following scenario:
  • Begin an asynchronous write operation
  • Call WaitCommEvent before any comm events have been recorded internally to the serial driver
  • Don't initiate any further write operations
I am referring to the driver at https://github.com/Microsoft/Windows-driver-samples/tree/master/serial/serial

There is an internal flag called EmptiedTransmit that is set to true when a write is initiated and set to false when a wait is initiated. EmptiedTransmit is a precondition for setting the EV_TXEMPTY at completion of a write.

jmcurl wrote Aug 27, 2015 at 8:03 PM

The purpose of Flush() is to ensure that the data has been transmitted from the hardware serial buffers before it returns, so we're pretty confident that the remote device should have received the bytes. What do you think if I implement a workaround that polls the hardware buffers in case a flush is waiting?

If so, what is an acceptable time to wait for the poll? 500ms? 200ms?

I'll have to look at the code and the patch in detail on the weekend.

jmcurl wrote Sep 26, 2015 at 5:58 PM

Please test against r33068. That should contain the fix.

jmcurl wrote Sep 26, 2015 at 5:59 PM

Sorry - please ignore this comment. I posted to the wrong ticket.

wrote Sep 28, 2015 at 8:12 AM

dhsmith wrote Sep 28, 2015 at 4:58 PM

Oops, I forgot to respond to this last month.. Sorry about that.

I wonder if the right answer is just to take out the Flush() method entirely.. There's no way to force the driver to flush its contents, so really this method at best can only cause confusion. Of course, that means breaking some code for people upgrading to the latest version, so that may not be appropriate either.

jmcurl wrote Sep 28, 2015 at 6:32 PM

My biggest concern is usage with hardware flow control, where one should know if the device has received all the data before doing another operation.

I appreciate your analysis in the MS sources. I would prefer to find a workaround, do you have a test in mind? I've got an old computer with a 16550A that should be using the standard MS port driver, perhaps I can wire that up with a NULL modem cable.