Signed-off-by: Guillaume Charifi guillaume.charifi@sfr.fr --- dlls/ntdll/unix/socket.c | 6 ++--- include/wine/afd.h | 2 +- server/protocol.def | 1 + server/sock.c | 52 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 8469def786a..b1b90b363ee 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -747,12 +747,11 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi || in_size < offsetof( struct afd_poll_params, sockets[params->count] )) return STATUS_INVALID_PARAMETER;
- TRACE( "timeout %s, count %u, unknown %#x, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n", - wine_dbgstr_longlong(params->timeout), params->count, params->unknown, + TRACE( "timeout %s, count %u, exclusive %u, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n", + wine_dbgstr_longlong(params->timeout), params->count, params->exclusive, params->padding[0], params->padding[1], params->padding[2], params->sockets[0].socket, params->sockets[0].flags );
- if (params->unknown) FIXME( "unknown boolean is %#x\n", params->unknown ); if (params->padding[0]) FIXME( "padding[0] is %#x\n", params->padding[0] ); if (params->padding[1]) FIXME( "padding[1] is %#x\n", params->padding[1] ); if (params->padding[2]) FIXME( "padding[2] is %#x\n", params->padding[2] ); @@ -793,6 +792,7 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi SERVER_START_REQ( poll_socket ) { req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) ); + req->exclusive = !!params->exclusive; req->timeout = params->timeout; wine_server_add_data( req, input, params->count * sizeof(*input) ); wine_server_set_reply( req, async->sockets, params->count * sizeof(async->sockets[0]) ); diff --git a/include/wine/afd.h b/include/wine/afd.h index e67ecae25a9..f4682f464e8 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -104,7 +104,7 @@ struct afd_poll_params { LONGLONG timeout; unsigned int count; - BOOLEAN unknown; + BOOLEAN exclusive; BOOLEAN padding[3]; struct { diff --git a/server/protocol.def b/server/protocol.def index 133d6ad0552..c6da8576f39 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1450,6 +1450,7 @@ struct poll_socket_output
/* Perform an async poll on a socket */ @REQ(poll_socket) + int exclusive; async_data_t async; /* async I/O parameters */ timeout_t timeout; /* timeout */ VARARG(sockets,poll_socket_input); /* list of sockets to poll */ diff --git a/server/sock.c b/server/sock.c index 3c5f2612b51..8fc21e39da1 100644 --- a/server/sock.c +++ b/server/sock.c @@ -128,12 +128,14 @@ struct poll_req struct async *async; struct iosb *iosb; struct timeout_user *timeout; + int exclusive; unsigned int count; struct poll_socket_output *output; struct { struct sock *sock; int flags; + int main; } sockets[1]; };
@@ -2839,7 +2841,50 @@ static int poll_single_socket( struct sock *sock, int mask ) return get_poll_flags( sock, pollfd.revents ) & mask; }
-static void poll_socket( struct sock *poll_sock, struct async *async, timeout_t timeout, +static void poll_handle_exclusive(struct poll_req *req) +{ + struct poll_req *areq; + unsigned int i, j; + + for (i = 0; i < req->count; ++i) + { + int has_main = FALSE; + + LIST_FOR_EACH_ENTRY(areq, &poll_list, struct poll_req, entry) + { + for (j = 0; j < areq->count; ++j) + { + if (areq->sockets[j].sock != req->sockets[i].sock) + continue; + + if (!areq->sockets[j].main) + continue; + + has_main = TRUE; + + if (areq->exclusive && req->exclusive) + { + /* Previous exclusive main poll replaced by new exclusive poll */ + areq->sockets[j].main = FALSE; + + areq->iosb->status = STATUS_SUCCESS; + areq->iosb->out_data = areq->output; + areq->iosb->out_size = areq->count * sizeof(*areq->output); + async_terminate(areq->async, STATUS_ALERTED); + + has_main = FALSE; + } + + goto next; + } + } + + next: + req->sockets[i].main = !has_main; + } +} + +static void poll_socket( struct sock *poll_sock, struct async *async, int exclusive, timeout_t timeout, unsigned int count, const struct poll_socket_input *input ) { struct poll_socket_output *output; @@ -2880,11 +2925,14 @@ static void poll_socket( struct sock *poll_sock, struct async *async, timeout_t req->sockets[i].flags = input[i].flags; }
+ req->exclusive = exclusive; req->count = count; req->async = (struct async *)grab_object( async ); req->iosb = async_get_iosb( async ); req->output = output;
+ poll_handle_exclusive(req); + list_add_tail( &poll_list, &req->entry ); async_set_completion_callback( async, free_poll_req, req ); queue_async( &poll_sock->poll_q, async ); @@ -3285,7 +3333,7 @@ DECL_HANDLER(poll_socket)
if ((async = create_request_async( sock->fd, get_fd_comp_flags( sock->fd ), &req->async ))) { - poll_socket( sock, async, req->timeout, count, input ); + poll_socket( sock, async, req->exclusive, req->timeout, count, input ); reply->wait = async_handoff( async, NULL, 0 ); reply->options = get_fd_options( sock->fd ); release_object( async );