Module: wine Branch: master Commit: dc203dd83318b0addda1e09ac596005ba00ca6ef URL: http://source.winehq.org/git/wine.git/?a=commit;h=dc203dd83318b0addda1e09ac5...
Author: Alexandre Julliard julliard@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@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);