From c561d1f7091368c5e09735ab099eb4a656587dfb Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Fri, 10 Nov 2023 08:41:28 +1300 Subject: [PATCH v2 4/6] Remove pgwin32_select(). pgwin32_select(), used to replace select() in backend code on Windows, would need to be updated to use the new per-socket event handles. Since the last remaining user of select() in the backend is scheduled for replacement with the WaitEventSet API, it seems better to demolish it instead. Any extension code that is relying on select() with fake signals will still compile, but will no longer respond to signals. Hypothetical code like that is probably buggy anyway, because backend code should also be handling interrupts, and should switch to the various WaitEventSet APIs. --- src/backend/port/win32/socket.c | 200 -------------------------------- src/include/port/win32_port.h | 2 - 2 files changed, 202 deletions(-) diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c index a7fa98cb1d..d0cf08392f 100644 --- a/src/backend/port/win32/socket.c +++ b/src/backend/port/win32/socket.c @@ -867,203 +867,3 @@ pgwin32_send(SOCKET s, const void *buf, int len, int flags) return -1; } - - -/* - * Wait for activity on one or more sockets. - * While waiting, allow signals to run - * - * NOTE! Currently does not implement exceptfds check, - * since it is not used in postgresql! - */ -int -pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout) -{ - WSAEVENT events[FD_SETSIZE * 2]; /* worst case is readfds totally - * different from writefds, so - * 2*FD_SETSIZE sockets */ - SOCKET sockets[FD_SETSIZE * 2]; - int numevents = 0; - int i; - int r; - DWORD timeoutval = WSA_INFINITE; - FD_SET outreadfds; - FD_SET outwritefds; - int nummatches = 0; - - Assert(exceptfds == NULL); - - if (pgwin32_poll_signals()) - return -1; - - FD_ZERO(&outreadfds); - FD_ZERO(&outwritefds); - - /* - * Windows does not guarantee to log an FD_WRITE network event indicating - * that more data can be sent unless the previous send() failed with - * WSAEWOULDBLOCK. While our caller might well have made such a call, we - * cannot assume that here. Therefore, if waiting for write-ready, force - * the issue by doing a dummy send(). If the dummy send() succeeds, - * assume that the socket is in fact write-ready, and return immediately. - * Also, if it fails with something other than WSAEWOULDBLOCK, return a - * write-ready indication to let our caller deal with the error condition. - */ - if (writefds != NULL) - { - for (i = 0; i < writefds->fd_count; i++) - { - char c; - WSABUF buf; - DWORD sent; - - buf.buf = &c; - buf.len = 0; - - r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL); - if (r == 0 || WSAGetLastError() != WSAEWOULDBLOCK) - FD_SET(writefds->fd_array[i], &outwritefds); - } - - /* If we found any write-ready sockets, just return them immediately */ - if (outwritefds.fd_count > 0) - { - memcpy(writefds, &outwritefds, sizeof(fd_set)); - if (readfds) - FD_ZERO(readfds); - return outwritefds.fd_count; - } - } - - - /* Now set up for an actual select */ - - if (timeout != NULL) - { - /* timeoutval is in milliseconds */ - timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; - } - - if (readfds != NULL) - { - for (i = 0; i < readfds->fd_count; i++) - { - events[numevents] = WSACreateEvent(); - sockets[numevents] = readfds->fd_array[i]; - numevents++; - } - } - if (writefds != NULL) - { - for (i = 0; i < writefds->fd_count; i++) - { - if (!readfds || - !FD_ISSET(writefds->fd_array[i], readfds)) - { - /* If the socket is not in the read list */ - events[numevents] = WSACreateEvent(); - sockets[numevents] = writefds->fd_array[i]; - numevents++; - } - } - } - - for (i = 0; i < numevents; i++) - { - int flags = 0; - - if (readfds && FD_ISSET(sockets[i], readfds)) - flags |= FD_READ | FD_ACCEPT | FD_CLOSE; - - if (writefds && FD_ISSET(sockets[i], writefds)) - flags |= FD_WRITE | FD_CLOSE; - - if (WSAEventSelect(sockets[i], events[i], flags) != 0) - { - TranslateSocketError(); - /* release already-assigned event objects */ - while (--i >= 0) - WSAEventSelect(sockets[i], NULL, 0); - for (i = 0; i < numevents; i++) - WSACloseEvent(events[i]); - return -1; - } - } - - events[numevents] = pgwin32_signal_event; - r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE); - if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents)) - { - /* - * We scan all events, even those not signaled, in case more than one - * event has been tagged but Wait.. can only return one. - */ - WSANETWORKEVENTS resEvents; - - for (i = 0; i < numevents; i++) - { - ZeroMemory(&resEvents, sizeof(resEvents)); - if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) != 0) - elog(ERROR, "failed to enumerate network events: error code %d", - WSAGetLastError()); - /* Read activity? */ - if (readfds && FD_ISSET(sockets[i], readfds)) - { - if ((resEvents.lNetworkEvents & FD_READ) || - (resEvents.lNetworkEvents & FD_ACCEPT) || - (resEvents.lNetworkEvents & FD_CLOSE)) - { - FD_SET(sockets[i], &outreadfds); - - nummatches++; - } - } - /* Write activity? */ - if (writefds && FD_ISSET(sockets[i], writefds)) - { - if ((resEvents.lNetworkEvents & FD_WRITE) || - (resEvents.lNetworkEvents & FD_CLOSE)) - { - FD_SET(sockets[i], &outwritefds); - - nummatches++; - } - } - } - } - - /* Clean up all the event objects */ - for (i = 0; i < numevents; i++) - { - WSAEventSelect(sockets[i], NULL, 0); - WSACloseEvent(events[i]); - } - - if (r == WSA_WAIT_TIMEOUT) - { - if (readfds) - FD_ZERO(readfds); - if (writefds) - FD_ZERO(writefds); - return 0; - } - - /* Signal-like events. */ - if (r == WAIT_OBJECT_0 + numevents || r == WAIT_IO_COMPLETION) - { - pgwin32_dispatch_queued_signals(); - errno = EINTR; - if (readfds) - FD_ZERO(readfds); - if (writefds) - FD_ZERO(writefds); - return -1; - } - - /* Overwrite socket sets with our resulting values */ - if (readfds) - memcpy(readfds, &outreadfds, sizeof(fd_set)); - if (writefds) - memcpy(writefds, &outwritefds, sizeof(fd_set)); - return nummatches; -} diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h index a0ed6aaeaa..1b605d9403 100644 --- a/src/include/port/win32_port.h +++ b/src/include/port/win32_port.h @@ -492,7 +492,6 @@ extern int pgkill(int pid, int sig); #define listen(s, backlog) pgwin32_listen(s, backlog) #define accept(s, addr, addrlen) pgwin32_accept(s, addr, addrlen) #define connect(s, name, namelen) pgwin32_connect(s, name, namelen) -#define select(n, r, w, e, timeout) pgwin32_select(n, r, w, e, timeout) #define recv(s, buf, len, flags) pgwin32_recv(s, buf, len, flags) #define send(s, buf, len, flags) pgwin32_send(s, buf, len, flags) @@ -501,7 +500,6 @@ extern int pgwin32_bind(SOCKET s, struct sockaddr *addr, int addrlen); extern int pgwin32_listen(SOCKET s, int backlog); extern SOCKET pgwin32_accept(SOCKET s, struct sockaddr *addr, int *addrlen); extern int pgwin32_connect(SOCKET s, const struct sockaddr *name, int namelen); -extern int pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout); extern int pgwin32_recv(SOCKET s, char *buf, int len, int flags); extern int pgwin32_send(SOCKET s, const void *buf, int len, int flags); extern int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout); -- 2.42.0