https://bugs.winehq.org/show_bug.cgi?id=50955
florian.will@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |florian.will@gmail.com
--- Comment #4 from florian.will@gmail.com --- Created attachment 71900 --> https://bugs.winehq.org/attachment.cgi?id=71900 Wine test suite patch to (hopefully) reproduce this issue
ZusiDisplay is affected by this when a train reverses at a station and embedded/integrated displays are re-started by Zusi.
The attached wine testsuite patch reproduces this in different ways (but it fails on the Wine Testbot on Debian, probably due to a race condition where the child process takes longer than 100ms to open the listening socket). After a rather complex first attempt that actually spawns child processes to stay close to what ZusiDisplay and the BrokenClient/BrokenServer reproducer does, I found an easier way:
The same / a very similar issue occurs with just one single-threaded test case (called "test_port_reuse()") that sets up a listening socket, connects to that socket, then closes the connection and the listening socket, then does it again using the same listening port. On Windows, the test passes. Using wine on Linux, the second attempt fails because the port is still "in use" (actually in TIME_WAIT state).
It seems like TIME_WAIT on Windows doesn't affect listening at all, so applications are free to bind to and listen on a port just moments after the previous listening socket was closed. It looks like the Windows kernel just takes extra care to make TCP work despite TIME_WAIT, compared to Linux. As I understand it, TIME_WAIT should prevent new connections using the same <local_ip:local_port, remote_ip:remote_port> combination, so just listening on a port is not an issue as no connection has been made at that point. The remote end will probably use a different port next time (or the connection can be refused otherwise, or even accepted using a larger-than-before initial TCP sequence number).
I'm not sure if there is a good way to emulate this behavior in wine. One way that comes to mind is to set the SO_REUSEADDR socket option for AF_INET sockets before the call to bind() in wineserver . However, this will break other test cases because they expect bind()ing to the same address twice to fail. So the current wine behavior is too restrictive compared to Windows, but always using SO_REUSEADDR is too permissive, and I'm not sure if there is any sensible middle ground. Maybe being too permissive is acceptable in this case? I still need to test if that actually fixes the ZusiDisplay issue (via Proton) though.