https://bugs.winehq.org/show_bug.cgi?id=53486
--- Comment #10 from Jinoh Kang jinoh.kang.kr@gmail.com --- Created attachment 72887 --> https://bugs.winehq.org/attachment.cgi?id=72887 POLLOUT spurious falling edge test & epoll switch
Diagnosis:
foo_out_upnp.dll uses Windows Sockets in non-blocking mode for communicating with the UPnP media renderer. When requested to play an audio stream, the component enters an I/O loop that transmits the stream via a socket connected to the renderer.
When sending a chunk of data, the component first performs a select() call with NULL readfds, non-NULL writefds and exceptfds, and NULL timeout (infinite). *Regardless* of the returned status of the select call(), the component then proceeds to perform a send() call. If send() fails with *any* error status (including WSAEWOULDBLOCK), the component throws a C++ exception. This exception is then caught by a catch(...) block outside the I/O loop that *silently* ignores the exception.
It can be inferred from the algorithm above that, if a select() call completes successfully with a non-empty writefds set, the component expects that any immediately following send() call on a socket in the writefds set never fails with WSAEWOULDBLOCK.
On Linux, Wine implements WSA select() via either epoll or poll (if epoll is not available) in Wineserver. When send() is called, Wineserver performs a poll() call to test whether the I/O request is immediately satiable before handing off the I/O to the client. It appears that the first epoll or poll yields (E)POLLOUT, but the second poll does not. Note that, before the regression, the client simply attempted the socket I/O first without asking the server if the I/O was indeed immediately satiable; the second poll either did not exist or was insignificant as far as the semantics of send() were concerned.
Hypothesis 1:
There exists a bug that causes Wine's epoll loop to signal a spurious (E)POLLOUT condition, which is not detected by a subsequent poll() call.
To test hypothesis 1, would you test the attached patch *with* and *without* WINE_DISABLE_EPOLL=1 environment variable and post the output log here?