Alexandre Julliard : ws2_32: Lock the user output buffer during receives.
Alexandre Julliard
julliard at winehq.org
Tue Oct 3 15:39:52 CDT 2017
Module: wine
Branch: master
Commit: dc203dd83318b0addda1e09ac596005ba00ca6ef
URL: http://source.winehq.org/git/wine.git/?a=commit;h=dc203dd83318b0addda1e09ac596005ba00ca6ef
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Oct 3 13:36:40 2017 +0200
ws2_32: Lock the user output buffer during receives.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/ntdll.spec | 3 +++
dlls/ntdll/virtual.c | 33 +++++++++++++++++++++++++++++++++
dlls/ws2_32/socket.c | 4 +++-
dlls/ws2_32/tests/sock.c | 5 -----
4 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 5e27f0a..ab801ac 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1480,6 +1480,9 @@
@ cdecl wine_server_send_fd(long)
@ cdecl __wine_make_process_system()
+# Virtual memory
+@ cdecl __wine_locked_recvmsg(long ptr long)
+
# Version
@ cdecl wine_get_version() NTDLL_wine_get_version
@ cdecl wine_get_build_id() NTDLL_wine_get_build_id
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index d0d25c7..7bb4eb4 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -32,6 +32,9 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
@@ -1904,6 +1907,36 @@ ssize_t virtual_locked_pread( int fd, void *addr, size_t size, off_t offset )
}
+/***********************************************************************
+ * __wine_locked_recvmsg
+ */
+ssize_t CDECL __wine_locked_recvmsg( int fd, struct msghdr *hdr, int flags )
+{
+ sigset_t sigset;
+ size_t i;
+ BOOL has_write_watch = FALSE;
+ int err = EFAULT;
+
+ ssize_t ret = recvmsg( fd, hdr, flags );
+ if (ret != -1 || errno != EFAULT) return ret;
+
+ server_enter_uninterrupted_section( &csVirtual, &sigset );
+ for (i = 0; i < hdr->msg_iovlen; i++)
+ if (check_write_access( hdr->msg_iov[i].iov_base, hdr->msg_iov[i].iov_len, &has_write_watch ))
+ break;
+ if (i == hdr->msg_iovlen)
+ {
+ ret = recvmsg( fd, hdr, flags );
+ err = errno;
+ }
+ if (has_write_watch)
+ while (i--) update_write_watches( hdr->msg_iov[i].iov_base, hdr->msg_iov[i].iov_len, 0 );
+
+ server_leave_uninterrupted_section( &csVirtual, &sigset );
+ errno = err;
+ return ret;
+}
+
/***********************************************************************
* virtual_is_valid_code_address
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 681f340..79b9333 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -241,6 +241,8 @@ static struct interface_filter generic_interface_filter = {
};
#endif /* LINUX_BOUND_IF */
+extern ssize_t CDECL __wine_locked_recvmsg( int fd, struct msghdr *hdr, int flags );
+
/*
* The actual definition of WSASendTo, wrapped in a different function name
* so that internal calls from ws2_32 itself will not trigger programs like
@@ -2356,7 +2358,7 @@ static int WS2_recv( int fd, struct ws2_async *wsa, int flags )
hdr.msg_flags = 0;
#endif
- while ((n = recvmsg(fd, &hdr, flags)) == -1)
+ while ((n = __wine_locked_recvmsg( fd, &hdr, flags )) == -1)
{
if (errno != EINTR)
return -1;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 02f7473..91305f9 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -6962,13 +6962,10 @@ static void test_write_watch(void)
send(src, "test message", sizeof("test message"), 0);
ret = GetOverlappedResult( (HANDLE)dest, &ov, &bytesReturned, TRUE );
- todo_wine
- {
ok( ret, "GetOverlappedResult failed %u\n", GetLastError() );
ok( bytesReturned == sizeof("test message"), "wrong size %u\n", bytesReturned );
ok( !memcmp( base, "test ", 5 ), "wrong data %s\n", base );
ok( !memcmp( base + 0x4000, "message", 8 ), "wrong data %s\n", base + 0x4000 );
- }
count = 64;
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
@@ -6984,7 +6981,6 @@ static void test_write_watch(void)
bufs[1].len = 0x4000;
bufs[1].buf = base + 0x2000;
ret = WSARecvFrom( dest, bufs, 2, NULL, &flags, &addr, &addr_len, &ov, NULL);
- todo_wine
ok(ret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING,
"WSARecv failed - %d error %d\n", ret, GetLastError());
@@ -6992,7 +6988,6 @@ static void test_write_watch(void)
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 5, "wrong count %lu\n", count );
- todo_wine
ok( !base[0], "data set\n" );
send(src, "test message", sizeof("test message"), 0);
More information about the wine-cvs
mailing list