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.
https://bugs.winehq.org/show_bug.cgi?id=50591
--- Comment #1 from Aaron Knister aaron.knister@gmail.com --- I believe this is also relevant to bug 38690 and possibly bug 42882.
https://bugs.winehq.org/show_bug.cgi?id=50591
Janne janne.kekkonen@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |janne.kekkonen@gmail.com
--- Comment #2 from Janne janne.kekkonen@gmail.com --- Hello,
i tested patch in wine version 8.7 and TeraTerm version 4.105.
In my test i used USB serial port and device that sends string into serial bus with 1 second interval. When there is traffic on bus TeraTerm GUI turns very sluggish, for example menus seem not to open. Also there is no data shown on TeraTerm.
When device is unplugged from serial port data is shown on TeraTerm and GUI functionality returns normal.
I also tested putty (0.78) & realterm (3.0.1.45), in both of these new string is shown with 1 second intervals.
https://bugs.winehq.org/show_bug.cgi?id=50591
--- Comment #3 from Janne janne.kekkonen@gmail.com --- Hello,
it seems that i made mistake previously. I re-tested this patch and it seems to work.
Teraterm and Wine versions are the same as previously.
Test setup is the same. Device which is sending data with 1 second interval is connected to USB-serial port and serial port is read/monitored with tera term.
https://bugs.winehq.org/show_bug.cgi?id=50591
Zeb Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|ntdll |serial