0003-Remove-obsolete-Windows-select-and-UDP-support.patch
application/x-patch
Filename: 0003-Remove-obsolete-Windows-select-and-UDP-support.patch
Type: application/x-patch
Part: 2
Message:
Time to drop RADIUS support?
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0003
Subject: Remove obsolete Windows select() and UDP support.
| File | + | − |
|---|---|---|
| src/backend/port/win32/socket.c | 1 | 269 |
| src/include/port/win32_port.h | 0 | 2 |
From f7f4d0af1446043fc781c9cf8ef7d645c20e2832 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Fri, 23 Jan 2026 14:58:15 +1300
Subject: [PATCH 3/3] Remove obsolete Windows select() and UDP support.
Since the removal of RADIUS, there are no remaining users of select() in
the backend. All new code, be it in the tree or in extensions, should
be using the WaitEventSet API. Non-thread-safe code relating to UDP
sockets is also removed; it was relevant to the pgstat process (long
gone) and perhaps RADIUS.
With a bit of higher-level work to eradicate blocking sockets completely
from the backend, the non-thread-safe blocking code in the remaining
wrappers could also be deleted, but that isn't done here.
Reviewed-by:
Discussion:
---
src/backend/port/win32/socket.c | 270 +-------------------------------
src/include/port/win32_port.h | 2 -
2 files changed, 1 insertion(+), 271 deletions(-)
diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c
index 3aaf971e973..3fbdf591b19 100644
--- a/src/backend/port/win32/socket.c
+++ b/src/backend/port/win32/socket.c
@@ -33,7 +33,6 @@ int pgwin32_noblock = 0;
#undef listen
#undef accept
#undef connect
-#undef select
#undef recv
#undef send
@@ -165,24 +164,10 @@ pgwin32_poll_signals(void)
return 0;
}
-static int
-isDataGram(SOCKET s)
-{
- int type;
- int typelen = sizeof(type);
-
- if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &typelen))
- return 1;
-
- return (type == SOCK_DGRAM) ? 1 : 0;
-}
-
int
pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
{
static HANDLE waitevent = INVALID_HANDLE_VALUE;
- static SOCKET current_socket = INVALID_SOCKET;
- static int isUDP = 0;
HANDLE events[2];
int r;
@@ -199,15 +184,6 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
ereport(ERROR,
(errmsg_internal("could not reset socket waiting event: error code %lu", GetLastError())));
- /*
- * Track whether socket is UDP or not. (NB: most likely, this is both
- * useless and wrong; there is no reason to think that the behavior of
- * WSAEventSelect is different for TCP and UDP.)
- */
- if (current_socket != s)
- isUDP = isDataGram(s);
- current_socket = s;
-
/*
* Attach event to socket. NOTE: we must detach it again before
* returning, since other bits of code may try to attach other events to
@@ -222,47 +198,7 @@ pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
events[0] = pgwin32_signal_event;
events[1] = waitevent;
- /*
- * Just a workaround of unknown locking problem with writing in UDP socket
- * under high load: Client's pgsql backend sleeps infinitely in
- * WaitForMultipleObjectsEx, pgstat process sleeps in pgwin32_select().
- * So, we will wait with small timeout(0.1 sec) and if socket is still
- * blocked, try WSASend (see comments in pgwin32_select) and wait again.
- */
- if ((what & FD_WRITE) && isUDP)
- {
- for (;;)
- {
- r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
-
- if (r == WAIT_TIMEOUT)
- {
- char c;
- WSABUF buf;
- DWORD sent;
-
- buf.buf = &c;
- buf.len = 0;
-
- r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
- if (r == 0) /* Completed - means things are fine! */
- {
- WSAEventSelect(s, NULL, 0);
- return 1;
- }
- else if (WSAGetLastError() != WSAEWOULDBLOCK)
- {
- TranslateSocketError();
- WSAEventSelect(s, NULL, 0);
- return 0;
- }
- }
- else
- break;
- }
- }
- else
- r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
+ r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
WSAEventSelect(s, NULL, 0);
@@ -468,10 +404,6 @@ pgwin32_send(SOCKET s, const void *buf, int len, int flags)
wbuf.len = len;
wbuf.buf = (char *) buf;
- /*
- * Readiness of socket to send data to UDP socket may be not true: socket
- * can become busy again! So loop until send or error occurs.
- */
for (;;)
{
r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
@@ -504,203 +436,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 956c0b4b4c3..9feaf0249cb 100644
--- a/src/include/port/win32_port.h
+++ b/src/include/port/win32_port.h
@@ -497,7 +497,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)
@@ -506,7 +505,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 *addr, int addrlen);
-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.52.0