https://bugs.winehq.org/show_bug.cgi?id=50591
Bug ID: 50591 Summary: ReadFile schedules async read when ReadIntervalTimeout is MAXDWORD Product: Wine Version: 6.1 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: ntdll Assignee: wine-bugs@winehq.org Reporter: aaron.knister@gmail.com Distribution: ---
Created attachment 69269 --> https://bugs.winehq.org/attachment.cgi?id=69269 ntdll: NtReadFile async reads always return success when avail_mode TRUE
TeraTerm is ending up with missing data when it reads from a COM/Serial port.
TeraTerm sets ReadIntervalTimeout to MAXDWORD and then calls ReadFile asynchronously, and if there's pending IO it waits 1 second for the overlapped struct event to be signalled. If the signal is received, it processes the received I/O, else continues on and will perform another ReadFile. This is the code snippet:
if (!ReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]), InBuffSize-cv->InBuffCount,&C,&rol)) { if (GetLastError() == ERROR_IO_PENDING) { if (WaitForSingleObject(rol.hEvent, 1000) != WAIT_OBJECT_0) { C = 0; } else { GetOverlappedResult(cv->ComID,&rol,&C,FALSE); } }
What's happening in WINE, is ReadFile returns non-zero with ERROR_IO_PENDING and the WaitForSingleObject times out. The asynchronous read *does* complete after the timeout, but by that point the application has given up and moved on. I initially thought the application was at fault, because it should retry if the wait times out. However, in the documentation for ReadFile it points to documentation about COMMTIMEOUTS (https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commti...) which says the following:
A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received.
To me, that means Wine ought not to be triggering an asynchronous read when the comm timeout parameters are set as indicated above.
I coded a simple fix, which is in NtReadFile, if avail_mode is TRUE return success even if no bytes were read. See attached patch. It works for TeraTerm, I have no idea if it causes other regressions.