[PATCH v8 7/7] server: Replace redundant send_socket status fields with force_async boolean field.

Jinoh Kang jinoh.kang.kr at gmail.com
Wed Mar 23 12:25:28 CDT 2022


The 'status' field of send_socket_request is always either
STATUS_PENDING or STATUS_DEVICE_NOT_READY, and the 'total' field is
always zero.

Replace the 'status' field with 'force_async' boolean field, and get rid
of the 'total' field entirely.

Also, clean up the send_socket handler code a bit.

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---

Notes:
    v1 -> v2:
    - adjust patch for new field "data_size" in send_socket_request
    v2 -> v3: no changes
    v3 -> v4: no changes
    v4 -> v5: no changes
    v5 -> v6:
    - centralise status code computation in one place, even for bind errno
      translation
    v6 -> v7: no changes
    v7 -> v8: no changes

 dlls/ntdll/unix/socket.c |  8 ++------
 server/protocol.def      |  3 +--
 server/sock.c            | 41 +++++++++++-----------------------------
 3 files changed, 14 insertions(+), 38 deletions(-)

diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index 8e5a1825181..351028d4983 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -908,12 +908,9 @@ static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
     async->iov_cursor = 0;
     async->sent_len = 0;
 
-    status = force_async ? STATUS_PENDING : STATUS_DEVICE_NOT_READY;
-
     SERVER_START_REQ( send_socket )
     {
-        req->status = status;
-        req->total  = 0;
+        req->force_async = force_async;
         req->async  = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
         status = wine_server_call( req );
         wait_handle = wine_server_ptr_handle( reply->wait );
@@ -1116,8 +1113,7 @@ static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc,
 
     SERVER_START_REQ( send_socket )
     {
-        req->status = STATUS_PENDING;
-        req->total  = 0;
+        req->force_async = 1;
         req->async  = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
         status = wine_server_call( req );
         wait_handle = wine_server_ptr_handle( reply->wait );
diff --git a/server/protocol.def b/server/protocol.def
index 81b44aefd7c..d9bed6855e9 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1462,8 +1462,7 @@ enum server_fd_type
 /* Perform a send on a socket */
 @REQ(send_socket)
     async_data_t async;         /* async I/O parameters */
-    unsigned int status;        /* status of initial call */
-    unsigned int total;         /* number of bytes already sent */
+    int          force_async;   /* Force asynchronous mode? */
 @REPLY
     obj_handle_t wait;          /* handle to wait on for blocking send */
     unsigned int options;       /* device open options */
diff --git a/server/sock.c b/server/sock.c
index e3779940174..b403541fcbf 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -3508,10 +3508,11 @@ static void send_socket_completion_callback( void *private )
 DECL_HANDLER(send_socket)
 {
     struct sock *sock = (struct sock *)get_handle_obj( current->process, req->async.handle, 0, &sock_ops );
-    unsigned int status = req->status;
+    unsigned int status = STATUS_PENDING;
     timeout_t timeout = 0;
     struct async *async;
     struct fd *fd;
+    int bind_errno = 0;
 
     if (!sock) return;
     fd = sock->fd;
@@ -3520,7 +3521,6 @@ DECL_HANDLER(send_socket)
     {
         union unix_sockaddr unix_addr;
         socklen_t unix_len;
-        int bind_errno = 0;
         int unix_fd = get_unix_fd( fd );
 
         unix_len = get_unix_sockaddr_any( &unix_addr, sock->family );
@@ -3532,36 +3532,15 @@ DECL_HANDLER(send_socket)
             sock->addr_len = sockaddr_from_unix( &unix_addr, &sock->addr.addr, sizeof(sock->addr) );
             sock->bound = 1;
         }
-        else if (status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY)
-            status = sock_get_ntstatus( bind_errno ? bind_errno : errno );
+        else if (!bind_errno) bind_errno = errno;
     }
 
-    /* If we had a short write and the socket is nonblocking (and the client is
-     * not trying to force the operation to be asynchronous), return success.
-     * Windows actually refuses to send any data in this case, and returns
-     * EWOULDBLOCK, but we have no way of doing that. */
-    if (status == STATUS_DEVICE_NOT_READY && req->total && sock->nonblocking)
-        status = STATUS_SUCCESS;
+    if (!req->force_async && !sock->nonblocking && is_fd_overlapped( fd ))
+        timeout = (timeout_t)sock->sndtimeo * -10000;
 
-    /* send() returned EWOULDBLOCK or a short write, i.e. cannot send all data yet */
-    if (status == STATUS_DEVICE_NOT_READY && !sock->nonblocking)
-    {
-        /* Set a timeout on the async if necessary.
-         *
-         * We want to do this *only* if the client gave us STATUS_DEVICE_NOT_READY.
-         * If the client gave us STATUS_PENDING, it expects the async to always
-         * block (it was triggered by WSASend*() with a valid OVERLAPPED
-         * structure) and for the timeout not to be respected. */
-        if (is_fd_overlapped( fd ))
-            timeout = (timeout_t)sock->sndtimeo * -10000;
-
-        status = STATUS_PENDING;
-    }
-
-    if ((status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) && sock->wr_shutdown)
-        status = STATUS_PIPE_DISCONNECTED;
-
-    if ((status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) && !async_queued( &sock->write_q ))
+    if (bind_errno) status = sock_get_ntstatus( bind_errno );
+    else if (sock->wr_shutdown) status = STATUS_PIPE_DISCONNECTED;
+    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 space; if there's no space
@@ -3580,6 +3559,9 @@ DECL_HANDLER(send_socket)
         }
     }
 
+    if (status == STATUS_PENDING && !req->force_async && sock->nonblocking)
+        status = STATUS_DEVICE_NOT_READY;
+
     if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async )))
     {
         struct send_req *send_req;
@@ -3594,7 +3576,6 @@ DECL_HANDLER(send_socket)
         else if (status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY)
             status = STATUS_NO_MEMORY;
 
-        if (status == STATUS_SUCCESS) iosb->result = req->total;
         release_object( iosb );
 
         set_error( status );
-- 
2.34.1




More information about the wine-devel mailing list