-- v2: ws2_32: Test wait alertability in WSAGetOverlappedResult().
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ws2_32/socket.c | 2 +- dlls/ws2_32/tests/sock.c | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 5eb926a408b..930a4000b4e 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -765,7 +765,7 @@ SOCKET WINAPI accept( SOCKET s, struct sockaddr *addr, int *len ) NULL, 0, &accept_handle, sizeof(accept_handle) ); if (status == STATUS_PENDING) { - if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) + if (wait_event_alertable( sync_event ) == WAIT_FAILED) return SOCKET_ERROR; status = io.u.Status; } diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index cddc4c125ff..b0ef7647654 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -4648,10 +4648,37 @@ static SOCKET setup_connector_socket(const struct sockaddr_in *addr, int len, BO return connector; }
+struct connect_apc_func_param +{ + HANDLE event; + struct sockaddr_in addr; + SOCKET connector; + unsigned int apc_count; +}; + +static DWORD WINAPI test_accept_connect_thread(void *param) +{ + struct connect_apc_func_param *p = (struct connect_apc_func_param *)param; + + WaitForSingleObject(p->event, INFINITE); + p->connector = setup_connector_socket(&p->addr, sizeof(p->addr), FALSE); + ok(p->connector != INVALID_SOCKET, "failed connecting from APC func.\n"); + return 0; +} + +static void WINAPI connect_apc_func(ULONG_PTR param) +{ + struct connect_apc_func_param *p = (struct connect_apc_func_param *)param; + + ++p->apc_count; + SetEvent(p->event); +} + static void test_accept(void) { int ret; SOCKET server_socket, accepted = INVALID_SOCKET, connector; + struct connect_apc_func_param apc_param; struct sockaddr_in address; SOCKADDR_STORAGE ss, ss_empty; int socklen; @@ -4666,6 +4693,23 @@ static void test_accept(void) socklen = sizeof(address); server_socket = setup_server_socket(&address, &socklen);
+ memset(&apc_param, 0, sizeof(apc_param)); + apc_param.event = CreateEventW(NULL, FALSE, FALSE, NULL); + apc_param.addr = address; + /* Connecting directly from APC function randomly crashes on Windows for some reason, + * so do it from a thread and only signal it from the APC when we are in accept() call. */ + thread_handle = CreateThread(NULL, 0, test_accept_connect_thread, &apc_param, 0, NULL); + ret = QueueUserAPC(connect_apc_func, GetCurrentThread(), (ULONG_PTR)&apc_param); + ok(ret, "QueueUserAPC returned %d\n", ret); + accepted = accept(server_socket, NULL, NULL); + ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError()); + ok(apc_param.apc_count == 1, "APC was called %u times\n", apc_param.apc_count); + closesocket(accepted); + closesocket(apc_param.connector); + WaitForSingleObject(thread_handle, INFINITE); + CloseHandle(thread_handle); + CloseHandle(apc_param.event); + connector = setup_connector_socket(&address, socklen, FALSE); if (connector == INVALID_SOCKET) goto done;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ws2_32/socket.c | 2 +- dlls/ws2_32/tests/sock.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 930a4000b4e..267830cc88c 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1240,7 +1240,7 @@ int WINAPI connect( SOCKET s, const struct sockaddr *addr, int len ) free( params ); if (status == STATUS_PENDING) { - if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) return -1; + if (wait_event_alertable( sync_event ) == WAIT_FAILED) return -1; status = io.u.Status; } if (status) diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index b0ef7647654..70618408e90 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -8448,6 +8448,28 @@ static void test_connect(void) WSACloseEvent(overlapped.hEvent); closesocket(connector);
+ if (0) + { + /* Wait in connect() is alertable. This may take a very long time before connection fails, + * so disable the test. Testing with localhost is unreliable as that may avoid waiting in + * accept(). */ + connector = socket(AF_INET, SOCK_STREAM, 0); + ok(connector != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError()); + address.sin_addr.s_addr = inet_addr("8.8.8.8"); + address.sin_port = htons(255); + + apc_count = 0; + SleepEx(0, TRUE); + ok(apc_count == 0, "got apc_count %d.\n", apc_count); + bret = QueueUserAPC(apc_func, GetCurrentThread(), (ULONG_PTR)&apc_count); + ok(bret, "QueueUserAPC returned %d\n", bret); + iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); + ok(apc_count == 1, "got apc_count %d.\n", apc_count); + ok(iret == -1 && (WSAGetLastError() == WSAECONNREFUSED || WSAGetLastError() == WSAETIMEDOUT), + "unexpected iret %d, error %d.\n", iret, WSAGetLastError()); + closesocket(connector); + } + /* Test connect after previous connect attempt failure. */ connector = socket(AF_INET, SOCK_STREAM, 0); ok(connector != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ws2_32/socket.c | 2 +- dlls/ws2_32/tests/sock.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 267830cc88c..710ec8cbb26 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2994,7 +2994,7 @@ int WINAPI WSAPoll( WSAPOLLFD *fds, ULONG count, int timeout ) params, params_size, params, params_size ); if (status == STATUS_PENDING) { - if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) + if (wait_event_alertable( sync_event ) == WAIT_FAILED) { free( params ); return -1; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 70618408e90..ff2364b9d1d 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -8127,7 +8127,11 @@ static void test_WSAPoll(void) fds[0].fd = client; fds[0].events = POLLRDNORM | POLLRDBAND; fds[0].revents = 0xdead; + apc_count = 0; + ret = QueueUserAPC(apc_func, GetCurrentThread(), (ULONG_PTR)&apc_count); + ok(ret, "QueueUserAPC returned %d\n", ret); ret = pWSAPoll(fds, 1, 2000); + ok(apc_count == 1, "APC was called %u times\n", apc_count); ok(ret == 1, "got %d\n", ret); ok(fds[0].revents == POLLNVAL, "got events %#x\n", fds[0].revents); ret = WaitForSingleObject(thread_handle, 1000);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ws2_32/tests/sock.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ff2364b9d1d..5f0c1850040 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -12662,6 +12662,20 @@ static void test_WSAGetOverlappedResult(void) } }
+ overlapped.Internal = STATUS_PENDING; + overlapped.hEvent = CreateEventW(NULL, TRUE, TRUE, NULL); + + apc_count = 0; + ret = QueueUserAPC(apc_func, GetCurrentThread(), (ULONG_PTR)&apc_count); + ok(ret, "QueueUserAPC returned %d\n", ret); + ret = WSAGetOverlappedResult(s, &overlapped, &size, TRUE, &flags); + ok(ret && (GetLastError() == ERROR_IO_PENDING || !WSAGetLastError()), + "Got ret %d, err %lu.\n", ret, GetLastError()); + ok(!apc_count, "got apc_count %d.\n", apc_count); + SleepEx(0, TRUE); + ok(apc_count == 1, "got apc_count %d.\n", apc_count); + + CloseHandle(overlapped.hEvent); closesocket(s); }
This merge request was approved by Zebediah Figura.