diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 63487f349f5..f6e4d04ea1a 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -7136,15 +7136,22 @@ clear_socket_set(socket_set *sa) static void add_socket_to_set(socket_set *sa, int fd, int idx) { - if (fd < 0 || fd >= FD_SETSIZE) + /* See connect_slot() for background on this code. */ +#ifdef WIN32 + if (sa->fds.fd_count + 1 >= FD_SETSIZE) { - /* - * Doing a hard exit here is a bit grotty, but it doesn't seem worth - * complicating the API to make it less grotty. - */ - pg_log_fatal("too many client connections for select()"); + pg_log_fatal("too many concurrent database clients for this platform: %d", + sa->fds.fd_count + 1); exit(1); } +#else + if (fd < 0 || fd >= FD_SETSIZE) + { + pg_log_fatal("socket file descriptor out of range for select(): %d", + fd); + exit(1); + } +#endif FD_SET(fd, &sa->fds); if (fd > sa->maxfd) sa->maxfd = fd; diff --git a/src/fe_utils/parallel_slot.c b/src/fe_utils/parallel_slot.c index dcdad9e30c5..8d558064343 100644 --- a/src/fe_utils/parallel_slot.c +++ b/src/fe_utils/parallel_slot.c @@ -297,11 +297,40 @@ connect_slot(ParallelSlotArray *sa, int slotno, const char *dbname) slot->connection = connectDatabase(sa->cparams, sa->progname, sa->echo, false, true); sa->cparams->override_dbname = old_override; - if (PQsocket(slot->connection) >= FD_SETSIZE) + /* + * POSIX defines FD_SETSIZE as the highest file descriptor acceptable to + * FD_SET() and allied macros. Windows defines it as a ceiling on the + * count of file descriptors in the set, not a ceiling on the value of + * each file descriptor; see + * https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select + * and + * https://learn.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-fd_set. + * We can't ignore that, because Windows starts file descriptors at a + * higher value, delays reuse, and skips values. With less than ten + * concurrent file descriptors, opened and closed rapidly, one can reach + * file descriptor 1024. + * + * Doing a hard exit here is a bit grotty, but it doesn't seem worth + * complicating the API to make it less grotty. + */ +#ifdef WIN32 + if (slotno >= FD_SETSIZE) { - pg_log_fatal("too many jobs for this platform"); + pg_log_fatal("too many jobs for this platform: %d", slotno); exit(1); } +#else + { + int fd = PQsocket(slot->connection); + + if (fd >= FD_SETSIZE) + { + pg_log_fatal("socket file descriptor out of range for select(): %d", + fd); + exit(1); + } + } +#endif /* Setup the connection using the supplied command, if any. */ if (sa->initcmd)