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