[PATCH 2/2] ws2_32: Invalidate client-side file descriptor cache in WSACleanup.
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Mon Apr 8 19:37:45 CDT 2019
From: Sebastian Lackner <sebastian at fds-team.de>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
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
More information about the wine-devel
mailing list