Jacek Caban : server: Create ifchange async queue on socket fd.

Alexandre Julliard julliard at winehq.org
Thu Oct 13 14:34:02 CDT 2016


Module: wine
Branch: master
Commit: 60f8ddbf9d372948674733169fcafc04c3d4827d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=60f8ddbf9d372948674733169fcafc04c3d4827d

Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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 );




More information about the wine-cvs mailing list