From: Alistair Leslie-Hughes Subject: [PATCH 2/2] ws2_32: Invalidate client-side file descriptor cache in WSACleanup. Message-Id: Date: Tue, 9 Apr 2019 00:37:45 +0000 In-Reply-To: <1554770254-1379-1-git-send-email-leslie_alistair@hotmail.com> References: <1554770254-1379-1-git-send-email-leslie_alistair@hotmail.com> From: Sebastian Lackner Signed-off-by: Alistair Leslie-Hughes --- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/server.c | 24 ++++++++++++++++++++++++ dlls/ws2_32/socket.c | 1 + dlls/ws2_32/tests/sock.c | 5 +---- include/wine/server.h | 1 + 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 292b0f6..157be4b 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1499,6 +1499,7 @@ # Server interface @ cdecl -norelay wine_server_call(ptr) +@ cdecl wine_server_close_fds_by_type(long) @ cdecl wine_server_fd_to_handle(long long long ptr) @ cdecl wine_server_handle_to_fd(long long ptr ptr) @ cdecl wine_server_release_fd(long long) diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 094b530..df1590a 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -921,6 +921,30 @@ int server_remove_fd_from_cache( HANDLE handle ) /*********************************************************************** + * wine_server_close_fds_by_type + * + * Needed for a proper implementation of WSACleanup. + */ +void CDECL wine_server_close_fds_by_type( enum server_fd_type type ) +{ + union fd_cache_entry cache; + unsigned int entry, idx; + + for (entry = 0; entry < FD_CACHE_ENTRIES; entry++) + { + if (!fd_cache[entry]) continue; + for (idx = 0; idx < FD_CACHE_BLOCK_SIZE; idx++) + { + cache.data = interlocked_cmpxchg64( &fd_cache[entry][idx].data, 0, 0 ); + if (cache.s.type != type || cache.s.fd == 0) continue; + if (interlocked_cmpxchg64( &fd_cache[entry][idx].data, 0, cache.data ) != cache.data) continue; + close( cache.s.fd - 1 ); + } + } +} + + +/*********************************************************************** * server_get_unix_fd * * The returned unix_fd should be closed iff needs_close is non-zero. diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index a2b9aea..f75d780 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1705,6 +1705,7 @@ INT WINAPI WSACleanup(void) if (!--num_startup) { + wine_server_close_fds_by_type( FD_TYPE_SOCKET ); SERVER_START_REQ(socket_cleanup) { wine_server_call( req ); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index f0fa8f0..270d147 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1248,10 +1248,7 @@ static void test_WithWSAStartup(void) SetLastError(0xdeadbeef); res = getsockname(sock, (struct sockaddr *)&saddr, &size); error = WSAGetLastError(); - if (j == 2 || (j == 0 && i == 0)) - todo_wine ok(res == SOCKET_ERROR, "Test[%d]: getsockname should have failed\n", i); - else - ok(res == SOCKET_ERROR, "Test[%d]: getsockname should have failed\n", i); + ok(res == SOCKET_ERROR, "Test[%d]: getsockname should have failed\n", i); todo_wine ok(error == WSAENOTSOCK, "Test[%d]: expected 10038, got %d\n", i, error); } } diff --git a/include/wine/server.h b/include/wine/server.h index d573d1f..02d9c7b 100644 --- a/include/wine/server.h +++ b/include/wine/server.h @@ -54,6 +54,7 @@ extern void CDECL wine_server_send_fd( int fd ); extern int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle ); extern int CDECL wine_server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd, unsigned int *options ); extern void CDECL wine_server_release_fd( HANDLE handle, int unix_fd ); +extern void CDECL wine_server_close_fds_by_type( enum server_fd_type type ); /* do a server call and set the last error code */ static inline unsigned int wine_server_call_err( void *req_ptr ) -- 1.9.1