ws2_32: Don't post completion packet if receiving fails with error immediately.

Signed-off-by: Stefan Dösinger <stefan@codeweavers.com>
Signed-off-by: Bruno Jesus <bjesus@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Stefan Dösinger 2017-05-15 19:06:32 +02:00 committed by Alexandre Julliard
parent be12c5bc4f
commit 7a1142035d
2 changed files with 162 additions and 2 deletions

View File

@ -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;
}
}

View File

@ -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)
{