diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 5e3c724f807..23059e3cff8 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -737,13 +737,9 @@ static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi } } - status = force_async ? STATUS_PENDING : STATUS_DEVICE_NOT_READY; - information = 0; - SERVER_START_REQ( recv_socket ) { - req->status = status; - req->total = information; + req->force_async = force_async; req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) ); req->oob = !!(unix_flags & MSG_OOB); status = wine_server_call( req ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index be63b290353..e32ef8e1479 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1764,8 +1764,8 @@ struct recv_socket_request struct request_header __header; int oob; async_data_t async; - unsigned int status; - unsigned int total; + int force_async; + char __pad_60[4]; }; struct recv_socket_reply { @@ -6284,7 +6284,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 745 +#define SERVER_PROTOCOL_VERSION 746 /* ### protocol_version end ### */ diff --git a/server/protocol.def b/server/protocol.def index 5c0f9a86822..9d90544fa41 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1451,8 +1451,7 @@ enum server_fd_type @REQ(recv_socket) int oob; /* are we receiving OOB data? */ async_data_t async; /* async I/O parameters */ - unsigned int status; /* status of initial call */ - unsigned int total; /* number of bytes already read */ + int force_async; /* Force asynchronous mode? */ @REPLY obj_handle_t wait; /* handle to wait on for blocking recv */ unsigned int options; /* device open options */ diff --git a/server/request.h b/server/request.h index 98e23bfd4ba..2c7889bd197 100644 --- a/server/request.h +++ b/server/request.h @@ -1044,8 +1044,7 @@ C_ASSERT( FIELD_OFFSET(struct unlock_file_request, count) == 24 ); C_ASSERT( sizeof(struct unlock_file_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct recv_socket_request, oob) == 12 ); C_ASSERT( FIELD_OFFSET(struct recv_socket_request, async) == 16 ); -C_ASSERT( FIELD_OFFSET(struct recv_socket_request, status) == 56 ); -C_ASSERT( FIELD_OFFSET(struct recv_socket_request, total) == 60 ); +C_ASSERT( FIELD_OFFSET(struct recv_socket_request, force_async) == 56 ); C_ASSERT( sizeof(struct recv_socket_request) == 64 ); C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, wait) == 8 ); C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, options) == 12 ); diff --git a/server/sock.c b/server/sock.c index 38aaaac9e39..91f98556552 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3396,7 +3396,7 @@ struct object *create_socket_device( struct object *root, const struct unicode_s DECL_HANDLER(recv_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; @@ -3404,29 +3404,16 @@ DECL_HANDLER(recv_socket) if (!sock) return; fd = sock->fd; - /* recv() returned EWOULDBLOCK, i.e. no data available 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 WSARecv*() with a valid OVERLAPPED - * structure) and for the timeout not to be respected. */ - if (is_fd_overlapped( fd )) - timeout = (timeout_t)sock->rcvtimeo * -10000; - - status = STATUS_PENDING; - } - - if ((status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) && sock->rd_shutdown) - status = STATUS_PIPE_DISCONNECTED; - - /* NOTE: If read_q is not empty, we cannot really tell if the already queued asyncs - * NOTE: will not consume all available data; if there's no data available, - * NOTE: the current request won't be immediately satiable. */ - if ((status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) && !async_queued( &sock->read_q )) + if (!req->force_async && !sock->nonblocking && is_fd_overlapped( fd )) + timeout = (timeout_t)sock->rcvtimeo * -10000; + + if (sock->rd_shutdown) status = STATUS_PIPE_DISCONNECTED; + else if (!async_queued( &sock->read_q )) { + /* If read_q is not empty, we cannot really tell if the already queued + * asyncs will not consume all available data; if there's no data + * available, the current request won't be immediately satiable. + */ struct pollfd pollfd; pollfd.fd = get_unix_fd( sock->fd ); pollfd.events = req->oob ? POLLPRI : POLLIN; @@ -3440,17 +3427,14 @@ DECL_HANDLER(recv_socket) } } + if (status == STATUS_PENDING && !req->force_async && sock->nonblocking) + status = STATUS_DEVICE_NOT_READY; + sock->pending_events &= ~(req->oob ? AFD_POLL_OOB : AFD_POLL_READ); sock->reported_events &= ~(req->oob ? AFD_POLL_OOB : AFD_POLL_READ); if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async ))) { - if (status == STATUS_SUCCESS) - { - struct iosb *iosb = async_get_iosb( async ); - iosb->result = req->total; - release_object( iosb ); - } set_error( status ); if (timeout) diff --git a/server/trace.c b/server/trace.c index 1fb39d4f997..61e592b0ffa 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2032,8 +2032,7 @@ static void dump_recv_socket_request( const struct recv_socket_request *req ) { fprintf( stderr, " oob=%d", req->oob ); dump_async_data( ", async=", &req->async ); - fprintf( stderr, ", status=%08x", req->status ); - fprintf( stderr, ", total=%08x", req->total ); + fprintf( stderr, ", force_async=%d", req->force_async ); } static void dump_recv_socket_reply( const struct recv_socket_reply *req )