Description
Hello,
We have been using this library for some time and we have encountered an issue which is very difficult to reproduce and debug. The problem is caused by the Read function in the windows implementation:
func (port *windowsPort) Read(p []byte) (int, error) {
var readed uint32
params := &dcb{}
ev, err := createOverlappedEvent()
if err != nil {
return 0, err
}
defer syscall.CloseHandle(ev.HEvent)
for {
err := syscall.ReadFile(port.handle, p, &readed, ev)
switch err {
case nil:
// operation completed successfully
case syscall.ERROR_IO_PENDING:
// wait for overlapped I/O to complete
if err := getOverlappedResult(port.handle, ev, &readed, true); err != nil {
return int(readed), err
}
default:
// error happened
return int(readed), err
}
if readed > 0 {
return int(readed), nil
}
if err := resetEvent(ev.HEvent); err != nil {
return 0, err
}
// At the moment it seems that the only reliable way to check if
// a serial port is alive in Windows is to check if the SetCommState
// function fails.
getCommState(port.handle, params)
if err := setCommState(port.handle, params); err != nil {
port.Close()
return 0, err
}
}
}
If there is no traffic on the port this function calls setCommState every 1 second. If there is also an ongoing Write operation at the same time, the transmitted data gets malformed and the other side receives gibberish. The race condition requires very precise timing to be reproduced. We are very confident that the issue is not caused by our code.
As this library is used by your customers I thought this may be quite critical information for you. We have spent around two days hunting this down. Feel free to contact me for more details.
Thank you for implementing this awesome library.