• Jinoh Kang's avatar
    server: Always prefer synchronous I/O in nonblocking mode. · a115feab
    Jinoh Kang authored
    foobar2000.exe's UPnP Media Renderer component (foo_out_upnp.dll)
    expects that, if a select() call completes successfully with a non-empty
    writefds set, any immediately following send() call on a socket in the
    writefds set never fails with WSAEWOULDBLOCK.
    
    On Wine, the Winsock select() and send() implementations both call the
    Unix poll(2) under the hood to test if I/O is possible on the socket.
    As it turns out, it's entirely possible that Linux poll() may yield
    POLLOUT on the first call (by select) but *not* the second (by send),
    even if no send() call has been made in the meanwhile.
    
    On Linux (as of v5.19), a connected (ESTABLISHED) TCP socket that has
    not been shut down indicates (E)POLLOUT only if the ratio of
    sk_wmem_queued (the amount of bytes queued in the send buffer) to
    sk_sndbuf (the size of send buffer size itself, which can be retrieved
    via SO_SNDBUF) is below a certain threshold.  Therefore, a falling edge
    in POLLOUT can be triggered due to a number of reasons:
    
    1. TCP fragmentation.  Once a TCP packet is split out from a larger
       sk_buff, it incurs extra bookkeeping overhead (e.g. sk_buff header)
       that is counted in sk_wmem_queued alongside application data.
       See also: tcp_fragment(), tso_fragment() (Linux 5.19).
    
    2. Control packets (e.g. MTU probing).  Such packets share the same
       buffer with application-initiated packets, and thus counted in
       sk_wmem_queued.
       See also: sk_wmem_queued_add() callers (Linux 5.19).
    
    3. Memory pressure.  This causes sk_sndbuf to shrink.
       See also: sk_stream_moderate_sndbuf() callers (Linux 5.19).
    
    Fix this by always attempting synchronous I/O first if req->force_async
    is unset and the nonblocking flag is set.
    
    Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53486
    a115feab
Name
Last commit
Last update
..
Makefile.in Loading commit data...
async.c Loading commit data...
atom.c Loading commit data...
change.c Loading commit data...
class.c Loading commit data...
clipboard.c Loading commit data...
completion.c Loading commit data...
console.c Loading commit data...
debugger.c Loading commit data...
device.c Loading commit data...
directory.c Loading commit data...
event.c Loading commit data...
fd.c Loading commit data...
file.c Loading commit data...
file.h Loading commit data...
handle.c Loading commit data...
handle.h Loading commit data...
hook.c Loading commit data...
mach.c Loading commit data...
mailslot.c Loading commit data...
main.c Loading commit data...
mapping.c Loading commit data...
mutex.c Loading commit data...
named_pipe.c Loading commit data...
object.c Loading commit data...
object.h Loading commit data...
process.c Loading commit data...
process.h Loading commit data...
procfs.c Loading commit data...
protocol.def Loading commit data...
ptrace.c Loading commit data...
queue.c Loading commit data...
region.c Loading commit data...
registry.c Loading commit data...
request.c Loading commit data...
request.h Loading commit data...
security.h Loading commit data...
semaphore.c Loading commit data...
serial.c Loading commit data...
signal.c Loading commit data...
sock.c Loading commit data...
symlink.c Loading commit data...
thread.c Loading commit data...
thread.h Loading commit data...
timer.c Loading commit data...
token.c Loading commit data...
trace.c Loading commit data...
unicode.c Loading commit data...
unicode.h Loading commit data...
user.c Loading commit data...
user.h Loading commit data...
window.c Loading commit data...
wineserver.de.UTF-8.man.in Loading commit data...
wineserver.fr.UTF-8.man.in Loading commit data...
wineserver.man.in Loading commit data...
winstation.c Loading commit data...