Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v3: appease Vista again...
dlls/ws2_32/tests/sock.c | 194 ++++++++++++++++++++++++++------------- 1 file changed, 130 insertions(+), 64 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 05e5cdd62ad..5da92361bbd 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6700,98 +6700,164 @@ static void test_shutdown(void)
static void test_DisconnectEx(void) { - SOCKET listener, acceptor, connector; + struct sockaddr_in server_addr, client_addr, addr; + GUID disconnectex_guid = WSAID_DISCONNECTEX; + SOCKET listener, server, client; LPFN_DISCONNECTEX pDisconnectEx; - GUID disconnectExGuid = WSAID_DISCONNECTEX; - struct sockaddr_in address; - DWORD num_bytes, flags; - OVERLAPPED overlapped; - int addrlen, iret; - BOOL bret; + OVERLAPPED overlapped = {0}; + int addrlen, ret; + char buffer[5]; + DWORD size;
- connector = socket(AF_INET, SOCK_STREAM, 0); - ok(connector != INVALID_SOCKET, "failed to create connector socket, error %d\n", WSAGetLastError()); + overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
- iret = WSAIoctl(connector, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnectExGuid, sizeof(disconnectExGuid), - &pDisconnectEx, sizeof(pDisconnectEx), &num_bytes, NULL, NULL); - if (iret) + client = socket(AF_INET, SOCK_STREAM, 0); + ok(client != INVALID_SOCKET, "failed to create connector socket, error %u\n", WSAGetLastError()); + + ret = WSAIoctl(client, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnectex_guid, sizeof(disconnectex_guid), + &pDisconnectEx, sizeof(pDisconnectEx), &size, NULL, NULL); + if (ret) { win_skip("WSAIoctl failed to get DisconnectEx, error %d\n", WSAGetLastError()); - closesocket(connector); + closesocket(client); return; }
listener = socket(AF_INET, SOCK_STREAM, 0); ok(listener != INVALID_SOCKET, "failed to create listener socket, error %d\n", WSAGetLastError());
- memset(&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_addr.s_addr = inet_addr("127.0.0.1"); - iret = bind(listener, (struct sockaddr *)&address, sizeof(address)); - ok(iret == 0, "failed to bind, error %d\n", WSAGetLastError()); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + ret = bind(listener, (struct sockaddr *)&addr, sizeof(addr)); + ok(!ret, "failed to bind, error %u\n", WSAGetLastError()); + addrlen = sizeof(server_addr); + ret = getsockname(listener, (struct sockaddr *)&server_addr, &addrlen); + ok(!ret, "failed to get address, error %u\n", WSAGetLastError()); + ret = listen(listener, 1); + ok(!ret, "failed to listen, error %u\n", WSAGetLastError());
- addrlen = sizeof(address); - iret = getsockname(listener, (struct sockaddr *)&address, &addrlen); - ok(iret == 0, "failed to lookup bind address, error %d\n", WSAGetLastError()); + WSASetLastError(0xdeadbeef); + ret = pDisconnectEx(INVALID_SOCKET, &overlapped, 0, 0); + ok(!ret, "expected failure\n"); + ok(WSAGetLastError() == WSAENOTSOCK, "got error %u\n", WSAGetLastError());
- iret = listen(listener, 1); - ok(iret == 0, "failed to listen, error %d\n", WSAGetLastError()); + WSASetLastError(0xdeadbeef); + ret = pDisconnectEx(client, &overlapped, 0, 0); + ok(!ret, "expected failure\n"); + todo_wine ok(WSAGetLastError() == WSAENOTCONN, "got error %u\n", WSAGetLastError());
- set_blocking(listener, TRUE); + ret = connect(client, (struct sockaddr *)&server_addr, sizeof(server_addr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != INVALID_SOCKET, "failed to accept, error %u\n", WSAGetLastError());
- memset(&overlapped, 0, sizeof(overlapped)); - bret = pDisconnectEx(INVALID_SOCKET, &overlapped, 0, 0); - ok(bret == FALSE, "DisconnectEx unexpectedly succeeded\n"); - ok(WSAGetLastError() == WSAENOTSOCK, "expected WSAENOTSOCK, got %d\n", WSAGetLastError()); + WSASetLastError(0xdeadbeef); + ret = pDisconnectEx(client, &overlapped, 0, 0); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(WSAGetLastError() == ERROR_IO_PENDING, "got error %u\n", WSAGetLastError());
- memset(&overlapped, 0, sizeof(overlapped)); - bret = pDisconnectEx(connector, &overlapped, 0, 0); - ok(bret == FALSE, "DisconnectEx unexpectedly succeeded\n"); - todo_wine ok(WSAGetLastError() == WSAENOTCONN, "expected WSAENOTCONN, got %d\n", WSAGetLastError()); + if (WSAGetLastError() == ERROR_IO_PENDING) + { + ret = WaitForSingleObject(overlapped.hEvent, 1000); + ok(!ret, "wait timed out\n"); + size = 0xdeadbeef; + ret = GetOverlappedResult((HANDLE)client, &overlapped, &size, FALSE); + ok(ret, "got error %u\n", GetLastError()); + ok(!size, "got size %u\n", size); + }
- iret = connect(connector, (struct sockaddr *)&address, addrlen); - ok(iret == 0, "failed to connect, error %d\n", WSAGetLastError()); + ret = connect(client, (struct sockaddr *)&server_addr, sizeof(server_addr)); + ok(ret == -1, "expected failure\n"); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError());
- acceptor = accept(listener, NULL, NULL); - ok(acceptor != INVALID_SOCKET, "could not accept socket, error %d\n", WSAGetLastError()); + WSASetLastError(0xdeadbeef); + ret = send(client, "test", 5, 0); + ok(ret == -1, "expected failure\n"); + todo_wine ok(WSAGetLastError() == WSAESHUTDOWN, "got error %u\n", WSAGetLastError());
- memset(&overlapped, 0, sizeof(overlapped)); - overlapped.hEvent = WSACreateEvent(); - ok(overlapped.hEvent != WSA_INVALID_EVENT, "WSACreateEvent failed, error %d\n", WSAGetLastError()); - bret = pDisconnectEx(connector, &overlapped, 0, 0); - if (bret) - ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal); - else if (WSAGetLastError() == ERROR_IO_PENDING) - bret = WSAGetOverlappedResult(connector, &overlapped, &num_bytes, TRUE, &flags); - ok(bret, "DisconnectEx failed, error %d\n", WSAGetLastError()); - WSACloseEvent(overlapped.hEvent); + ret = recv(server, buffer, sizeof(buffer), 0); + ok(!ret, "got %d\n", ret);
- iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); - ok(iret != 0, "connect unexpectedly succeeded\n"); - ok(WSAGetLastError() == WSAEISCONN, "expected WSAEISCONN, got %d\n", WSAGetLastError()); + ret = send(server, "test", 5, 0); + ok(ret == 5, "got %d\n", ret);
- closesocket(acceptor); - closesocket(connector); + ret = recv(client, buffer, sizeof(buffer), 0); + ok(ret == 5, "got %d\n", ret); + ok(!strcmp(buffer, "test"), "got %s\n", debugstr_an(buffer, ret));
- connector = socket(AF_INET, SOCK_STREAM, 0); - ok(connector != INVALID_SOCKET, "failed to create connector socket, error %d\n", WSAGetLastError()); + addrlen = sizeof(addr); + ret = getpeername(client, (struct sockaddr *)&addr, &addrlen); + ok(!ret, "got error %u\n", WSAGetLastError()); + ok(!memcmp(&addr, &server_addr, sizeof(server_addr)), "address didn't match\n");
- iret = connect(connector, (struct sockaddr *)&address, addrlen); - ok(iret == 0, "failed to connect, error %d\n", WSAGetLastError()); + addrlen = sizeof(client_addr); + ret = getsockname(client, (struct sockaddr *)&client_addr, &addrlen); + ok(!ret, "got error %u\n", WSAGetLastError()); + addrlen = sizeof(addr); + ret = getpeername(server, (struct sockaddr *)&addr, &addrlen); + ok(!ret, "got error %u\n", WSAGetLastError()); + ok(!memcmp(&addr, &client_addr, sizeof(addr)), "address didn't match\n");
- acceptor = accept(listener, NULL, NULL); - ok(acceptor != INVALID_SOCKET, "could not accept socket, error %d\n", WSAGetLastError()); + closesocket(client); + closesocket(server);
- bret = pDisconnectEx(connector, NULL, 0, 0); - ok(bret, "DisconnectEx failed, error %d\n", WSAGetLastError()); + /* Test the synchronous case. */
- iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); - ok(iret != 0, "connect unexpectedly succeeded\n"); - ok(WSAGetLastError() == WSAEISCONN, "expected WSAEISCONN, got %d\n", WSAGetLastError()); + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + ret = connect(client, (struct sockaddr *)&server_addr, sizeof(server_addr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != -1, "failed to accept, error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + ret = pDisconnectEx(client, NULL, 0, 0); + ok(ret, "expected success\n"); + ok(!WSAGetLastError() || WSAGetLastError() == 0xdeadbeef /* < 7 */, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + ret = pDisconnectEx(client, NULL, 0, 0); + todo_wine ok(ret, "expected success\n"); + todo_wine ok(!WSAGetLastError() || WSAGetLastError() == 0xdeadbeef /* < 7 */, "got error %u\n", WSAGetLastError()); + + ret = connect(client, (struct sockaddr *)&server_addr, sizeof(server_addr)); + ok(ret == -1, "expected failure\n"); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + ret = send(client, "test", 5, 0); + ok(ret == -1, "expected failure\n"); + todo_wine ok(WSAGetLastError() == WSAESHUTDOWN, "got error %u\n", WSAGetLastError()); + + ret = recv(server, buffer, sizeof(buffer), 0); + ok(!ret, "got %d\n", ret); + + ret = send(server, "test", 5, 0); + ok(ret == 5, "got %d\n", ret); + + ret = recv(client, buffer, sizeof(buffer), 0); + ok(ret == 5, "got %d\n", ret); + ok(!strcmp(buffer, "test"), "got %s\n", debugstr_an(buffer, ret)); + + addrlen = sizeof(addr); + ret = getpeername(client, (struct sockaddr *)&addr, &addrlen); + ok(!ret, "got error %u\n", WSAGetLastError()); + ok(!memcmp(&addr, &server_addr, sizeof(server_addr)), "address didn't match\n"); + + addrlen = sizeof(client_addr); + ret = getsockname(client, (struct sockaddr *)&client_addr, &addrlen); + ok(!ret, "got error %u\n", WSAGetLastError()); + addrlen = sizeof(addr); + ret = getpeername(server, (struct sockaddr *)&addr, &addrlen); + ok(!ret, "got error %u\n", WSAGetLastError()); + ok(!memcmp(&addr, &client_addr, sizeof(addr)), "address didn't match\n"); + + closesocket(client); + closesocket(server);
- closesocket(acceptor); - closesocket(connector); closesocket(listener); + CloseHandle(overlapped.hEvent); }
#define compare_file(h,s,o) compare_file2(h,s,o,__FILE__,__LINE__)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v3: appease Vista again...
dlls/ws2_32/tests/sock.c | 188 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 5da92361bbd..ec78e62969e 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -8469,6 +8469,193 @@ static void test_connect_completion_port(void) CloseHandle(port); }
+static void test_shutdown_completion_port(void) +{ + OVERLAPPED overlapped = {0}, *overlapped_ptr; + GUID disconnectex_guid = WSAID_DISCONNECTEX; + struct sockaddr_in addr, destaddr; + LPFN_DISCONNECTEX pDisconnectEx; + SOCKET listener, server, client; + int ret, addrlen; + ULONG_PTR key; + HANDLE port; + DWORD size; + + overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + + listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(listener != -1, "failed to create socket, error %u\n", WSAGetLastError()); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + ret = bind(listener, (struct sockaddr *)&addr, sizeof(addr)); + ok(!ret, "failed to bind, error %u\n", WSAGetLastError()); + addrlen = sizeof(destaddr); + ret = getsockname(listener, (struct sockaddr *)&destaddr, &addrlen); + ok(!ret, "failed to get address, error %u\n", WSAGetLastError()); + + ret = listen(listener, 1); + ok(!ret, "failed to listen, error %u\n", WSAGetLastError()); + + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + + ret = WSAIoctl(client, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnectex_guid, sizeof(disconnectex_guid), + &pDisconnectEx, sizeof(pDisconnectEx), &size, NULL, NULL); + ok(!ret, "Failed to get ConnectEx, error %u\n", WSAGetLastError()); + + /* shutdown() does not queue completion. */ + + port = CreateIoCompletionPort((HANDLE)client, NULL, 0, 0); + ok(!!port, "failed to create port, error %u\n", GetLastError()); + ret = connect(client, (struct sockaddr *)&destaddr, sizeof(destaddr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != -1, "failed to accept, error %u\n", WSAGetLastError()); + + ret = shutdown(client, SD_BOTH); + ok(!ret, "failed to shutdown, error %u\n", WSAGetLastError()); + + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + ok(!ret, "expected failure\n"); + ok(GetLastError() == WAIT_TIMEOUT, "got error %u\n", GetLastError()); + + closesocket(server); + closesocket(client); + CloseHandle(port); + + /* WSASendDisconnect() and WSARecvDisconnect() do not queue completion. */ + + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + port = CreateIoCompletionPort((HANDLE)client, NULL, 0, 0); + ok(!!port, "failed to create port, error %u\n", GetLastError()); + ret = connect(client, (struct sockaddr *)&destaddr, sizeof(destaddr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != -1, "failed to accept, error %u\n", WSAGetLastError()); + + ret = WSASendDisconnect(client, NULL); + ok(!ret, "failed to shutdown, error %u\n", WSAGetLastError()); + + ret = WSARecvDisconnect(client, NULL); + ok(!ret, "failed to shutdown, error %u\n", WSAGetLastError()); + + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + ok(!ret, "expected failure\n"); + ok(GetLastError() == WAIT_TIMEOUT, "got error %u\n", GetLastError()); + + closesocket(server); + closesocket(client); + CloseHandle(port); + + /* DisconnectEx() queues completion. */ + + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + port = CreateIoCompletionPort((HANDLE)client, NULL, 0, 0); + ok(!!port, "failed to create port, error %u\n", GetLastError()); + ret = SetFileCompletionNotificationModes((HANDLE)client, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS); + ok(ret, "got error %u\n", GetLastError()); + ret = connect(client, (struct sockaddr *)&destaddr, sizeof(destaddr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != -1, "failed to accept, error %u\n", WSAGetLastError()); + + SetLastError(0xdeadbeef); + ret = pDisconnectEx(client, &overlapped, 0, 0); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got error %u\n", GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + { + ret = WaitForSingleObject(overlapped.hEvent, 1000); + ok(!ret, "wait failed\n"); + + size = 0xdeadbeef; + ret = GetOverlappedResult((HANDLE)client, &overlapped, &size, TRUE); + ok(ret, "got error %u\n", GetLastError()); + ok(!size, "got %u bytes\n", size); + } + + size = 0xdeadbeef; + key = 0xdeadbeef; + overlapped_ptr = NULL; + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + todo_wine ok(ret, "got error %u\n", GetLastError()); + todo_wine ok(!key, "got key %#Ix\n", key); + todo_wine ok(!size, "got %u bytes\n", size); + todo_wine ok(overlapped_ptr == &overlapped, "got overlapped %p\n", overlapped_ptr); + + closesocket(server); + closesocket(client); + CloseHandle(port); + + /* Test passing a NULL overlapped structure to DisconnectEx(). */ + + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + port = CreateIoCompletionPort((HANDLE)client, NULL, 0, 0); + ok(!!port, "failed to create port, error %u\n", GetLastError()); + ret = connect(client, (struct sockaddr *)&destaddr, sizeof(destaddr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != -1, "failed to accept, error %u\n", WSAGetLastError()); + + SetLastError(0xdeadbeef); + ret = pDisconnectEx(client, NULL, 0, 0); + ok(ret, "expected success\n"); + ok(!GetLastError() || GetLastError() == 0xdeadbeef /* < 7 */, "got error %u\n", GetLastError()); + + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + ok(!ret, "expected failure\n"); + ok(GetLastError() == WAIT_TIMEOUT, "got error %u\n", GetLastError()); + + closesocket(server); + closesocket(client); + CloseHandle(port); + + /* Suppress completion by setting the low bit. */ + + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + port = CreateIoCompletionPort((HANDLE)client, NULL, 0, 0); + ok(!!port, "failed to create port, error %u\n", GetLastError()); + ret = connect(client, (struct sockaddr *)&destaddr, sizeof(destaddr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + server = accept(listener, NULL, NULL); + ok(server != -1, "failed to accept, error %u\n", WSAGetLastError()); + + overlapped.hEvent = (HANDLE)((ULONG_PTR)overlapped.hEvent | 1); + + SetLastError(0xdeadbeef); + ret = pDisconnectEx(client, &overlapped, 0, 0); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got error %u\n", GetLastError()); + if (GetLastError() == ERROR_IO_PENDING) + { + ret = WaitForSingleObject(overlapped.hEvent, 1000); + ok(!ret, "wait failed\n"); + + size = 0xdeadbeef; + ret = GetOverlappedResult((HANDLE)client, &overlapped, &size, TRUE); + ok(ret, "got error %u\n", GetLastError()); + ok(!size, "got %u bytes\n", size); + } + + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + ok(!ret, "expected failure\n"); + ok(GetLastError() == WAIT_TIMEOUT, "got error %u\n", GetLastError()); + + closesocket(server); + closesocket(client); + CloseHandle(port); + + overlapped.hEvent = (HANDLE)((ULONG_PTR)overlapped.hEvent & ~1); + + CloseHandle(overlapped.hEvent); +} + static void test_address_list_query(void) { SOCKET_ADDRESS_LIST *address_list; @@ -9766,6 +9953,7 @@ START_TEST( sock )
test_completion_port(); test_connect_completion_port(); + test_shutdown_completion_port(); test_address_list_query(); test_bind(); test_connecting_socket();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/sock.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 6891b5cbc57..791e4912c89 100644 --- a/server/sock.c +++ b/server/sock.c @@ -612,50 +612,40 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) return event; }
+static void post_socket_event( struct sock *sock, unsigned int event_bit, unsigned int error ) +{ + unsigned int event = (1 << event_bit); + + sock->pmask |= event; + sock->hmask |= event; + sock->errors[event_bit] = error; +} + static void sock_dispatch_events( struct sock *sock, int prevstate, int event, int error ) { if (prevstate & FD_CONNECT) { - sock->pmask |= FD_CONNECT; - sock->hmask |= FD_CONNECT; - sock->errors[FD_CONNECT_BIT] = sock_get_error( error ); + post_socket_event( sock, FD_CONNECT_BIT, sock_get_error( error ) ); goto end; } if (prevstate & FD_WINE_LISTENING) { - sock->pmask |= FD_ACCEPT; - sock->hmask |= FD_ACCEPT; - sock->errors[FD_ACCEPT_BIT] = sock_get_error( error ); + post_socket_event( sock, FD_ACCEPT_BIT, sock_get_error( error ) ); goto end; }
if (event & POLLIN) - { - sock->pmask |= FD_READ; - sock->hmask |= FD_READ; - sock->errors[FD_READ_BIT] = 0; - } + post_socket_event( sock, FD_READ_BIT, 0 );
if (event & POLLOUT) - { - sock->pmask |= FD_WRITE; - sock->hmask |= FD_WRITE; - sock->errors[FD_WRITE_BIT] = 0; - } + post_socket_event( sock, FD_WRITE_BIT, 0 );
if (event & POLLPRI) - { - sock->pmask |= FD_OOB; - sock->hmask |= FD_OOB; - sock->errors[FD_OOB_BIT] = 0; - } + post_socket_event( sock, FD_OOB_BIT, 0 );
if (event & (POLLERR|POLLHUP)) - { - sock->pmask |= FD_CLOSE; - sock->hmask |= FD_CLOSE; - sock->errors[FD_CLOSE_BIT] = sock_get_error( error ); - } + post_socket_event( sock, FD_CLOSE_BIT, sock_get_error( error ) ); + end: sock_wake_up( sock ); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- The difference between state, mask, pmask, and hmask I found very difficult to understand. Part of this is I think bad organization ("state" in particular is overloaded for several different purposes and should just go away); part of it is excessively terse naming, and part is bad commenting (in particular, "held" is very confusing). Try to address at least the latter two (the former I intend to address later, but ideally only after other restructuring).
server/sock.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 791e4912c89..8b0b56f4070 100644 --- a/server/sock.c +++ b/server/sock.c @@ -112,8 +112,8 @@ struct sock struct fd *fd; /* socket file descriptor */ unsigned int state; /* status bits */ unsigned int mask; /* event mask */ + unsigned int pending_events; /* pending FD_* events which have not yet been reported to the application */ unsigned int hmask; /* held (blocked) events */ - unsigned int pmask; /* pending events */ unsigned int flags; /* socket flags */ int polling; /* is socket being polled? */ unsigned short proto; /* socket protocol */ @@ -386,7 +386,7 @@ static int sock_reselect( struct sock *sock ) /* wake anybody waiting on the socket event or send the associated message */ static void sock_wake_up( struct sock *sock ) { - unsigned int events = sock->pmask & sock->mask; + unsigned int events = sock->pending_events & sock->mask; int i;
if ( !events ) return; @@ -402,13 +402,13 @@ static void sock_wake_up( struct sock *sock ) for (i = 0; i < FD_MAX_EVENTS; i++) { int event = event_bitorder[i]; - if (sock->pmask & (1 << event)) + if (sock->pending_events & (1 << event)) { lparam_t lparam = (1 << event) | (sock->errors[event] << 16); post_message( sock->window, sock->message, sock->wparam, lparam ); } } - sock->pmask = 0; + sock->pending_events = 0; sock_reselect( sock ); } } @@ -616,7 +616,7 @@ static void post_socket_event( struct sock *sock, unsigned int event_bit, unsign { unsigned int event = (1 << event_bit);
- sock->pmask |= event; + sock->pending_events |= event; sock->hmask |= event; sock->errors[event_bit] = error; } @@ -745,7 +745,7 @@ static void sock_dump( struct object *obj, int verbose ) assert( obj->ops == &sock_ops ); fprintf( stderr, "Socket fd=%p, state=%x, mask=%x, pending=%x, held=%x\n", sock->fd, sock->state, - sock->mask, sock->pmask, sock->hmask ); + sock->mask, sock->pending_events, sock->hmask ); }
static int sock_get_poll_events( struct fd *fd ) @@ -893,7 +893,7 @@ static struct sock *create_socket(void) sock->state = 0; sock->mask = 0; sock->hmask = 0; - sock->pmask = 0; + sock->pending_events = 0; sock->polling = 0; sock->flags = 0; sock->proto = 0; @@ -1143,7 +1143,7 @@ static struct sock *accept_socket( struct sock *sock ) } } clear_error(); - sock->pmask &= ~FD_ACCEPT; + sock->pending_events &= ~FD_ACCEPT; sock->hmask &= ~FD_ACCEPT; sock_reselect( sock ); return acceptsock; @@ -1180,7 +1180,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
acceptsock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE; acceptsock->hmask = 0; - acceptsock->pmask = 0; + acceptsock->pending_events = 0; acceptsock->polling = 0; acceptsock->proto = sock->proto; acceptsock->type = sock->type; @@ -1193,7 +1193,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock ) acceptsock->fd = newfd;
clear_error(); - sock->pmask &= ~FD_ACCEPT; + sock->pending_events &= ~FD_ACCEPT; sock->hmask &= ~FD_ACCEPT; sock_reselect( sock );
@@ -1801,7 +1801,7 @@ DECL_HANDLER(get_socket_event) FILE_READ_ATTRIBUTES, &sock_ops ))) return; if (get_unix_fd( sock->fd ) == -1) return; reply->mask = sock->mask; - reply->pmask = sock->pmask; + reply->pmask = sock->pending_events; reply->state = sock->state; set_reply_data( sock->errors, min( get_reply_max_size(), sizeof(sock->errors) ));
@@ -1817,7 +1817,7 @@ DECL_HANDLER(get_socket_event) release_object( cevent ); } } - sock->pmask = 0; + sock->pending_events = 0; sock_reselect( sock ); } release_object( &sock->obj ); @@ -1835,7 +1835,7 @@ DECL_HANDLER(enable_socket_event) if (get_unix_fd( sock->fd ) == -1) return;
/* for event-based notification, windows erases stale events */ - sock->pmask &= ~req->mask; + sock->pending_events &= ~req->mask;
sock->hmask &= ~req->mask; sock->state |= req->sstate;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/sock.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 8b0b56f4070..bd65cfc68c3 100644 --- a/server/sock.c +++ b/server/sock.c @@ -112,8 +112,19 @@ struct sock struct fd *fd; /* socket file descriptor */ unsigned int state; /* status bits */ unsigned int mask; /* event mask */ - unsigned int pending_events; /* pending FD_* events which have not yet been reported to the application */ - unsigned int hmask; /* held (blocked) events */ + /* pending FD_* events which have not yet been reported to the application */ + unsigned int pending_events; + /* FD_* events which have already been reported and should not be selected + * for again until reset by a relevant call. + * + * For example, if FD_READ is set here and not in pending_events, it has + * already been reported and consumed, and we should not report it again, + * even if POLLIN is signaled, until it is reset by e.g recv(). + * + * If an event has been signaled and not consumed yet, it will be set in + * both pending_events and reported_events (as we should only ever report + * any event once until it is reset.) */ + unsigned int reported_events; unsigned int flags; /* socket flags */ int polling; /* is socket being polled? */ unsigned short proto; /* socket protocol */ @@ -617,7 +628,7 @@ static void post_socket_event( struct sock *sock, unsigned int event_bit, unsign unsigned int event = (1 << event_bit);
sock->pending_events |= event; - sock->hmask |= event; + sock->reported_events |= event; sock->errors[event_bit] = error; }
@@ -743,15 +754,15 @@ static void sock_dump( struct object *obj, int verbose ) { struct sock *sock = (struct sock *)obj; assert( obj->ops == &sock_ops ); - fprintf( stderr, "Socket fd=%p, state=%x, mask=%x, pending=%x, held=%x\n", + fprintf( stderr, "Socket fd=%p, state=%x, mask=%x, pending=%x, reported=%x\n", sock->fd, sock->state, - sock->mask, sock->pending_events, sock->hmask ); + sock->mask, sock->pending_events, sock->reported_events ); }
static int sock_get_poll_events( struct fd *fd ) { struct sock *sock = get_fd_user( fd ); - unsigned int mask = sock->mask & ~sock->hmask; + unsigned int mask = sock->mask & ~sock->reported_events; unsigned int smask = sock->state & mask; int ev = 0;
@@ -773,7 +784,7 @@ static int sock_get_poll_events( struct fd *fd ) ev |= POLLIN | POLLPRI; /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */ else if (sock->type == WS_SOCK_STREAM && (sock->state & FD_READ) && (mask & FD_CLOSE) && - !(sock->hmask & FD_READ)) + !(sock->reported_events & FD_READ)) ev |= POLLIN;
if (async_queued( &sock->write_q )) @@ -892,8 +903,8 @@ static struct sock *create_socket(void) sock->fd = NULL; sock->state = 0; sock->mask = 0; - sock->hmask = 0; sock->pending_events = 0; + sock->reported_events = 0; sock->polling = 0; sock->flags = 0; sock->proto = 0; @@ -1144,7 +1155,7 @@ static struct sock *accept_socket( struct sock *sock ) } clear_error(); sock->pending_events &= ~FD_ACCEPT; - sock->hmask &= ~FD_ACCEPT; + sock->reported_events &= ~FD_ACCEPT; sock_reselect( sock ); return acceptsock; } @@ -1179,8 +1190,8 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock ) }
acceptsock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE; - acceptsock->hmask = 0; acceptsock->pending_events = 0; + acceptsock->reported_events = 0; acceptsock->polling = 0; acceptsock->proto = sock->proto; acceptsock->type = sock->type; @@ -1194,7 +1205,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
clear_error(); sock->pending_events &= ~FD_ACCEPT; - sock->hmask &= ~FD_ACCEPT; + sock->reported_events &= ~FD_ACCEPT; sock_reselect( sock );
return TRUE; @@ -1769,7 +1780,7 @@ DECL_HANDLER(set_socket_event) if (get_unix_fd( sock->fd ) == -1) return; old_event = sock->event; sock->mask = req->mask; - sock->hmask &= ~req->mask; /* re-enable held events */ + sock->reported_events &= ~req->mask; /* re-enable held events */ sock->event = NULL; sock->window = req->window; sock->message = req->msg; @@ -1837,7 +1848,7 @@ DECL_HANDLER(enable_socket_event) /* for event-based notification, windows erases stale events */ sock->pending_events &= ~req->mask;
- sock->hmask &= ~req->mask; + sock->reported_events &= ~req->mask; sock->state |= req->sstate; sock->state &= ~req->cstate; if (sock->type != WS_SOCK_STREAM) sock->state &= ~STREAM_FLAG_MASK;