This fixes the send part of the issue #52401 [1]: "Improper synchronization in sock_recv/sock_send leads to arbitrary reordering of completion of I/O requests", which was initially reported (outside Bugzilla) by Dongwan Kim [2].
Changelog: v1 -> v2: - drop patch "server: Compact struct set_async_direct_result_reply." - add async and fd arguments to async_initial_status_callback - recv_socket_initial_callback: pass OOB flag via private instead of implementing two separate functions for OOB and non-OOB - detect short write in send_socket_initial_callback - preserve the behaviour of returning success if we had a short write and the socket is nonblocking and force_async is unset v2 -> v3: - fix typo in comment
[1] https://bugs.winehq.org/show_bug.cgi?id=52401 [2] https://www.winehq.org/pipermail/wine-devel/2021-May/186454.html
Jinoh Kang (8): server: Actually set initial status in set_async_direct_result handler. server: Add async_initial_status_callback. server: Defer postprocessing until after setting initial status in recv_socket handler. server: Defer postprocessing until after setting initial status in send_socket handler. server: Add mark_pending field to set_async_direct_result request. server: Attempt to complete I/O request immediately in send_socket. ntdll: Don't call try_send before server call in sock_send. server: Replace redundant send_socket status fields with force_async boolean field.
dlls/ntdll/unix/socket.c | 102 ++++++++++++++++++++++-------- dlls/ntdll/unix/sync.c | 9 +-- dlls/ntdll/unix/unix_private.h | 2 +- dlls/ws2_32/tests/sock.c | 14 ++--- server/async.c | 52 +++++++++++++--- server/file.h | 2 + server/protocol.def | 6 +- server/sock.c | 110 +++++++++++++++++++-------------- 8 files changed, 204 insertions(+), 93 deletions(-)
Interdiff: diff --git a/server/sock.c b/server/sock.c index 2706c2d20ed..1112708369d 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3513,7 +3513,7 @@ DECL_HANDLER(send_socket) else if (!async_queued( &sock->write_q )) { /* If write_q is not empty, we cannot really tell if the already queued - * asyncs will not consume all available data; if there's no data + * asyncs will not consume all available space; if there's no space * available, the current request won't be immediately satiable. */ struct pollfd pollfd;