Module: wine Branch: master Commit: 60f8ddbf9d372948674733169fcafc04c3d4827d URL: http://source.winehq.org/git/wine.git/?a=commit;h=60f8ddbf9d372948674733169f...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Oct 12 17:11:50 2016 +0200
server: Create ifchange async queue on socket fd.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ws2_32/tests/sock.c | 30 +++++++++++++++++++++++++++++- server/sock.c | 18 ++++++------------ 2 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index b7aaea3..a144bd3 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -8345,12 +8345,15 @@ static void test_sioAddressListChange(void) { struct sockaddr_in bindAddress; struct in_addr net_address; - WSAOVERLAPPED overlapped; + WSAOVERLAPPED overlapped, *olp; struct hostent *h; DWORD num_bytes, error, tick; SOCKET sock, sock2, sock3; WSAEVENT event2, event3; + HANDLE io_port; + ULONG_PTR key; int acount; + BOOL bret; int ret;
/* Use gethostbyname to find the list of local network interfaces */ @@ -8465,8 +8468,33 @@ static void test_sioAddressListChange(void) ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %d\n", error); ok (error == WSAEWOULDBLOCK, "expected 10035, got %d\n", error);
+ io_port = CreateIoCompletionPort( (HANDLE)sock, NULL, 0, 0 ); + ok (io_port != NULL, "failed to create completion port %u\n", GetLastError()); + + set_blocking(sock, FALSE); + memset(&overlapped, 0, sizeof(overlapped)); + SetLastError(0xdeadbeef); + ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL); + error = GetLastError(); + ok (ret == SOCKET_ERROR, "WSAIoctl(SIO_ADDRESS_LIST_CHANGE) failed with error %u\n", error); + ok (error == ERROR_IO_PENDING, "expected ERROR_IO_PENDING got %u\n", error); + + olp = (WSAOVERLAPPED *)0xdeadbeef; + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 0 ); + ok(!bret, "failed to get completion status %u\n", bret); + ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError()); + ok(!olp, "Overlapped structure is at %p\n", olp); + closesocket(sock);
+ olp = (WSAOVERLAPPED *)0xdeadbeef; + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 0 ); + ok(!bret, "failed to get completion status %u\n", bret); + ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %u\n", GetLastError()); + ok(olp == &overlapped, "Overlapped structure is at %p\n", olp); + + CloseHandle(io_port); + /* Misuse of the API by using a blocking socket and not using an overlapped structure, * this leads to a hang forever. */ if (0) diff --git a/server/sock.c b/server/sock.c index d7349fc..0de6f68 100644 --- a/server/sock.c +++ b/server/sock.c @@ -606,7 +606,9 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, static void sock_reselect_async( struct fd *fd, struct async_queue *queue ) { struct sock *sock = get_fd_user( fd ); - sock_reselect( sock ); + /* ignore reselect on ifchange queue */ + if (sock->ifchange_q != queue) + sock_reselect( sock ); }
static int sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb ) @@ -640,6 +642,7 @@ static void sock_destroy( struct object *obj )
free_async_queue( sock->read_q ); free_async_queue( sock->write_q ); + async_wake_up( sock->ifchange_q, STATUS_CANCELLED ); sock_destroy_ifchange_q( sock ); if (sock->event) release_object( sock->event ); if (sock->fd) @@ -973,7 +976,6 @@ static void ifchange_destroy( struct object *obj );
static int ifchange_get_poll_events( struct fd *fd ); static void ifchange_poll_event( struct fd *fd, int event ); -static void ifchange_reselect_async( struct fd *fd, struct async_queue *queue );
struct ifchange { @@ -1014,7 +1016,7 @@ static const struct fd_ops ifchange_fd_ops = no_fd_flush, /* flush */ no_fd_ioctl, /* ioctl */ NULL, /* queue_async */ - ifchange_reselect_async, /* reselect_async */ + NULL, /* reselect_async */ NULL /* cancel_async */ };
@@ -1096,11 +1098,6 @@ static void ifchange_poll_event( struct fd *fd, int event ) if (status != STATUS_PENDING) ifchange_wake_up( ifchange, status ); }
-static void ifchange_reselect_async( struct fd *fd, struct async_queue *queue ) -{ - /* do nothing, this object is about to disappear */ -} - #endif
/* we only need one of these interface notification objects, all of the sockets dependent upon @@ -1174,7 +1171,6 @@ static void ifchange_add_sock( struct object *obj, struct sock *sock ) static struct async_queue *sock_get_ifchange_q( struct sock *sock ) { struct object *ifchange; - struct fd *fd;
if (sock->ifchange_q) /* reuse existing ifchange_q for this socket */ return sock->ifchange_q; @@ -1183,9 +1179,7 @@ static struct async_queue *sock_get_ifchange_q( struct sock *sock ) return NULL;
/* create the ifchange notification queue */ - fd = get_obj_fd( ifchange ); - sock->ifchange_q = create_async_queue( fd ); - release_object( fd ); + sock->ifchange_q = create_async_queue( sock->fd ); if (!sock->ifchange_q) { release_object( ifchange );