Skip to content

Commit 73cda80

Browse files
committed
Don't spuriously report FD_SETSIZE exhaustion on Windows.
Starting on 2023-08-03, this intermittently terminated a "pgbench -C" test in CI. It could affect a high-client-count "pgbench" without "-C". While parallel reindexdb and vacuumdb reach the same problematic check, sufficient client count and/or connection turnover is less plausible for them. Given the lack of examples from the buildfarm or from manual builds, reproducing this must entail rare operating system configurations. Also correct the associated error message, which was wrong for non-Windows. Back-patch to v12, where the pgbench check first appeared. While v11 vacuumdb has the problematic check, reaching it with typical vacuumdb usage is implausible. Reviewed by Thomas Munro. Discussion: https://postgr.es/m/CA+hUKG+JwvTNdcyJTriy9BbtzF1veSRQ=9M_ZKFn9_LqE7Kp7Q@mail.gmail.com
1 parent 3cc0c25 commit 73cda80

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

src/bin/pgbench/pgbench.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6377,15 +6377,24 @@ clear_socket_set(socket_set *sa)
63776377
static void
63786378
add_socket_to_set(socket_set *sa, int fd, int idx)
63796379
{
6380+
/* See connect_slot() for background on this code. */
6381+
#ifdef WIN32
6382+
if (sa->fds.fd_count + 1 >= FD_SETSIZE)
6383+
{
6384+
fprintf(stderr,
6385+
"too many concurrent database clients for this platform: %d\n",
6386+
sa->fds.fd_count + 1);
6387+
exit(1);
6388+
}
6389+
#else
63806390
if (fd < 0 || fd >= FD_SETSIZE)
63816391
{
6382-
/*
6383-
* Doing a hard exit here is a bit grotty, but it doesn't seem worth
6384-
* complicating the API to make it less grotty.
6385-
*/
6386-
fprintf(stderr, "too many client connections for select()\n");
6392+
fprintf(stderr,
6393+
"socket file descriptor out of range for select(): %d\n",
6394+
fd);
63876395
exit(1);
63886396
}
6397+
#endif
63896398
FD_SET(fd, &sa->fds);
63906399
if (fd > sa->maxfd)
63916400
sa->maxfd = fd;

src/bin/scripts/vacuumdb.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -635,15 +635,39 @@ vacuum_one_database(const ConnParams *cparams,
635635
conn = connectDatabase(cparams, progname, echo, false, true);
636636

637637
/*
638-
* Fail and exit immediately if trying to use a socket in an
639-
* unsupported range. POSIX requires open(2) to use the lowest
640-
* unused file descriptor and the hint given relies on that.
638+
* POSIX defines FD_SETSIZE as the highest file descriptor
639+
* acceptable to FD_SET() and allied macros. Windows defines it
640+
* as a ceiling on the count of file descriptors in the set, not a
641+
* ceiling on the value of each file descriptor; see
642+
* https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select
643+
* and
644+
* https://learn.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-fd_set.
645+
* We can't ignore that, because Windows starts file descriptors
646+
* at a higher value, delays reuse, and skips values. With less
647+
* than ten concurrent file descriptors, opened and closed
648+
* rapidly, one can reach file descriptor 1024.
649+
*
650+
* Doing a hard exit here is a bit grotty, but it doesn't seem
651+
* worth complicating the API to make it less grotty.
641652
*/
642-
if (PQsocket(conn) >= FD_SETSIZE)
653+
#ifdef WIN32
654+
if (i >= FD_SETSIZE)
643655
{
644-
pg_log_fatal("too many jobs for this platform -- try %d", i);
656+
pg_log_fatal("too many jobs for this platform: %d", i);
645657
exit(1);
646658
}
659+
#else
660+
{
661+
int fd = PQsocket(conn);
662+
663+
if (fd >= FD_SETSIZE)
664+
{
665+
pg_log_fatal("socket file descriptor out of range for select(): %d",
666+
fd);
667+
exit(1);
668+
}
669+
}
670+
#endif
647671

648672
init_slot(slots + i, conn);
649673
}

0 commit comments

Comments
 (0)