SerialPort: TimeoutException not always thrown for write timeouts
#20,370 opened on 2017年2月28日
Repository metrics
- Stars
- (17,886 stars)
- PR merge metrics
- (平均マージ 12d 11h) (30d で 661 merged PRs)
説明
With a 'real' (serial.sys / 16550) serial port, if you set up a WriteTimeout and then write to a port which is blocked by flow control, the write will eventually fail and throw a TimeoutException. This is the expected behaviour.
This exception is thrown by a code in SerialStream.Write, which looks like this:
if (numBytes == 0)
throw new TimeoutException(SR.Write_timed_out);
Where numBytes is passed back from the OS in the lpNumberOfBytesWritten argument of WriteFile.
With some usb serial devices (tested with FTDI) lpNumberOfBytesWritten is not zero in this situation - it's some non-zero number less than the size of the buffer which was written. It's probably related to the difference in size between the buffer written and the amount of internal buffering within the driver/hardware stack..
This might be characterised as a bug within the FTDI product, but it's probably very difficult to fix - they have committed a certain amount of data to the USB stack and their hardware device, and once that's gone from their serial driver it is hard to know that it never made it out of the pins of the IC at the end of the USB cable. It could be possibly made to work via reporting back from the hardware to the driver, but if that isn't in place in their existing protocol then it's probably not going to be.
This gives a situation where a Write has failed with a timeout but this fact is not visible to the application.
Instead of the numBytes == 0 test, we might consider having some other way of determining that a timeout occurred - perhaps something like numBytes < (bytesThatCouldbeWritten). I'm not currently sure what (bytesThatCouldbeWritten) would be, and how this would interact with overlapped writes, etc, but it's worth thinking about.
This can be left up-for-grabs for now.