From 7a1142035d7ee04839417176ff93fd0953e2a4e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20D=C3=B6singer?= Date: Mon, 15 May 2017 19:06:32 +0200 Subject: [PATCH] ws2_32: Don't post completion packet if receiving fails with error immediately. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Dösinger Signed-off-by: Bruno Jesus Signed-off-by: Alexandre Julliard --- dlls/ws2_32/socket.c | 2 - dlls/ws2_32/tests/sock.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index f6db83206a3..e464b58e3fa 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -7744,9 +7744,7 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, if (errno != EAGAIN) { - int loc_errno = errno; err = wsaErrno(); - if (cvalue) WS_AddCompletion( s, cvalue, sock_get_ntstatus(loc_errno), 0 ); goto error; } } diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 023eb423b85..57455c0df4b 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -9184,6 +9184,7 @@ static void test_completion_port(void) struct sockaddr_in bindAddress; GUID acceptExGuid = WSAID_ACCEPTEX; LPFN_ACCEPTEX pAcceptEx = NULL; + fd_set fds_recv; memset(buf, 0, sizeof(buf)); previous_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); @@ -9299,6 +9300,167 @@ static void test_completion_port(void) if (dest != INVALID_SOCKET) closesocket(dest); + /* Test IOCP response on successful immediate read. */ + tcp_socketpair(&src, &dest); + if (src == INVALID_SOCKET || dest == INVALID_SOCKET) + { + skip("failed to create sockets\n"); + goto end; + } + + bufs.len = sizeof(buf); + bufs.buf = buf; + flags = 0; + SetLastError(0xdeadbeef); + + iret = WSASend(src, &bufs, 1, &num_bytes, 0, &ov, NULL); + ok(!iret, "WSASend failed - %d, last error %u\n", iret, GetLastError()); + ok(num_bytes == sizeof(buf), "Managed to send %d\n", num_bytes); + + io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 125, 0); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + set_blocking(dest, FALSE); + + FD_ZERO(&fds_recv); + FD_SET(dest, &fds_recv); + select(dest + 1, &fds_recv, NULL, NULL, NULL); + + num_bytes = 0xdeadbeef; + flags = 0; + + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + ok(!iret, "WSARecv failed - %d, last error %u\n", iret, GetLastError()); + ok(num_bytes == sizeof(buf), "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + ok(bret == TRUE, "failed to get completion status %u\n", bret); + ok(GetLastError() == 0xdeadbeef, "Last error was %d\n", GetLastError()); + ok(key == 125, "Key is %lu\n", key); + ok(num_bytes == sizeof(buf), "Number of bytes transferred is %u\n", num_bytes); + ok(olp == &ov, "Overlapped structure is at %p\n", olp); + + /* Test IOCP response on graceful shutdown. */ + closesocket(src); + + FD_ZERO(&fds_recv); + FD_SET(dest, &fds_recv); + select(dest + 1, &fds_recv, NULL, NULL, NULL); + + num_bytes = 0xdeadbeef; + flags = 0; + memset(&ov, 0, sizeof(ov)); + + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + ok(!iret, "WSARecv failed - %d, last error %u\n", iret, GetLastError()); + ok(!num_bytes, "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + ok(bret == TRUE, "failed to get completion status %u\n", bret); + ok(GetLastError() == 0xdeadbeef, "Last error was %d\n", GetLastError()); + ok(key == 125, "Key is %lu\n", key); + ok(!num_bytes, "Number of bytes transferred is %u\n", num_bytes); + ok(olp == &ov, "Overlapped structure is at %p\n", olp); + + closesocket(src); + src = INVALID_SOCKET; + closesocket(dest); + dest = INVALID_SOCKET; + + /* Test IOCP response on hard shutdown. This was the condition that triggered + * a crash in an actual app (bug 38980). */ + tcp_socketpair(&src, &dest); + if (src == INVALID_SOCKET || dest == INVALID_SOCKET) + { + skip("failed to create sockets\n"); + goto end; + } + + bufs.len = sizeof(buf); + bufs.buf = buf; + flags = 0; + memset(&ov, 0, sizeof(ov)); + + ling.l_onoff = 1; + ling.l_linger = 0; + iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); + ok(!iret, "Failed to set linger %d\n", GetLastError()); + + io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 125, 0); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + set_blocking(dest, FALSE); + + closesocket(src); + src = INVALID_SOCKET; + + FD_ZERO(&fds_recv); + FD_SET(dest, &fds_recv); + select(dest + 1, &fds_recv, NULL, NULL, NULL); + + num_bytes = 0xdeadbeef; + SetLastError(0xdeadbeef); + + /* Somehow a hard shutdown doesn't work on my Linux box. It seems SO_LINGER is ignored. */ + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + todo_wine ok(iret == SOCKET_ERROR, "WSARecv failed - %d\n", iret); + todo_wine ok(GetLastError() == WSAECONNRESET, "Last error was %d\n", GetLastError()); + todo_wine ok(num_bytes == 0xdeadbeef, "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + todo_wine ok(bret == FALSE, "GetQueuedCompletionStatus returned %u\n", bret ); + todo_wine ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError()); + todo_wine ok(key == 0xdeadbeef, "Key is %lu\n", key); + todo_wine ok(num_bytes == 0xdeadbeef, "Number of bytes transferred is %u\n", num_bytes); + todo_wine ok(!olp, "Overlapped structure is at %p\n", olp); + + closesocket(dest); + + /* Test reading from a non-connected socket, mostly because the above test is marked todo. */ + dest = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(dest != INVALID_SOCKET, "socket() failed\n"); + + io_port = CreateIoCompletionPort((HANDLE)dest, previous_port, 125, 0); + ok(io_port != NULL, "failed to create completion port %u\n", GetLastError()); + set_blocking(dest, FALSE); + + num_bytes = 0xdeadbeef; + SetLastError(0xdeadbeef); + memset(&ov, 0, sizeof(ov)); + + iret = WSARecv(dest, &bufs, 1, &num_bytes, &flags, &ov, NULL); + ok(iret == SOCKET_ERROR, "WSARecv failed - %d\n", iret); + ok(GetLastError() == WSAENOTCONN, "Last error was %d\n", GetLastError()); + ok(num_bytes == 0xdeadbeef, "Managed to read %d\n", num_bytes); + + SetLastError(0xdeadbeef); + key = 0xdeadbeef; + num_bytes = 0xdeadbeef; + olp = (WSAOVERLAPPED *)0xdeadbeef; + + bret = GetQueuedCompletionStatus( io_port, &num_bytes, &key, &olp, 200 ); + ok(bret == FALSE, "GetQueuedCompletionStatus returned %u\n", bret ); + ok(GetLastError() == WAIT_TIMEOUT, "Last error was %d\n", GetLastError()); + ok(key == 0xdeadbeef, "Key is %lu\n", key); + ok(num_bytes == 0xdeadbeef, "Number of bytes transferred is %u\n", num_bytes); + ok(!olp, "Overlapped structure is at %p\n", olp); + + num_bytes = 0xdeadbeef; + closesocket(dest); + dest = socket(AF_INET, SOCK_STREAM, 0); if (dest == INVALID_SOCKET) { -- 2.11.4.GIT