=?UTF-8?Q?Stefan=20D=C3=B6singer=20?=: ws2_32: Don' t post completion packet if receiving fails with error immediately.
Alexandre Julliard
julliard at winehq.org
Fri Oct 20 07:19:57 CDT 2017
Module: wine
Branch: stable
Commit: f75720a58003052122d49e0377f8b403eba631cd
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f75720a58003052122d49e0377f8b403eba631cd
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Mon May 15 19:06:32 2017 +0200
ws2_32: Don't post completion packet if receiving fails with error immediately.
Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
Signed-off-by: Bruno Jesus <bjesus at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit 7a1142035d7ee04839417176ff93fd0953e2a4e1)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>
---
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 513cbfc..6e77d1a 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -7786,9 +7786,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 d7e7fff..dd0b1b3 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -9057,6 +9057,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);
@@ -9172,6 +9173,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)
{
More information about the wine-cvs
mailing list