On Mon Jun 30 21:26:07 2025 +0000, Alex Henrie wrote:
I can try to dig deeper when I get some free time, though in my opinion there's no harm in reverting to the pre-regression behavior in this case. When I originally wrote this code, it certainly wasn't my intention to skip the synchronous read when the timeout is infinite. That was an oversight on my part.
It helps a lot that [Ti99Hdx](https://hexbus.com/ti99geek/Projects/ti99hdx/ti99hdx_server.html) is [open source](https://hexbus.com/ti99geek/Projects/ti99hdx/Files/ti99hdx113a_src.zip). A timer set up via SetTimer calls the ReadSerialData function in Ti99HdxCom.cpp once every 10 milliseconds, and ReadSerialData does the following:
```cpp if (!ClearCommError(hSerCom, &dwErrors, &comStat)) { return 0; }
if ((dwRead = comStat.cbInQue) > 0) { if (dwRead > (unsigned int) Maxsize) dwRead = Maxsize; if (!ReadFile(hSerCom, Buffer, dwRead, &dwRead, &osSerCom)) { } else { return (int) dwRead; } } return 0; ```
The problem is that the program never actually checks the result of the osSerCom OVERLAPPED struct. It's requesting an asynchronous read, but then it expects data to be returned synchronously. In fact, it only calls ReadFile after checking that there is already data in the queue to be read. If no data is ever returned synchronously, dwRead is always 0, and the program doesn't do anything.
Ti99Hdx never sets the serial interval timeout; it uses the default infinite timeout. Should Wine return some data synchronously even if the program did set an interval timeout? Probably. On the other hand, is there actually a program that needs that? It's weird enough that we found a program that requests asynchronous I/O that it doesn't really want. Why would a program go so far as to set a timeout if it's not actually going to check the result of the asynchronous operation?