Skip to content

Commit

Permalink
Refactor ListenSocket array.
Browse files Browse the repository at this point in the history
Keep track of the used size of the array. That avoids looping through
the whole array in a few places. It doesn't matter from a performance
point of view since the array is small anyway, but this feels less
surprising and is a little less code. Now that we have an explicit
NumListenSockets variable that is statically initialized to 0, we
don't need the loop to initialize the array.

Allocate the array in PostmasterContext. The array isn't needed in
child processes, so this allows reusing that memory. We could easily
make the array resizable now, but we haven't heard any complaints
about the current 64 sockets limit.

Discussion: https://www.postgresql.org/message-id/7bb7ad65-a018-2419-742f-fa5fd877d338@iki.fi
  • Loading branch information
hlinnaka committed Oct 5, 2023
1 parent 1c99cde commit e29c464
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 61 deletions.
20 changes: 8 additions & 12 deletions src/backend/libpq/pqcomm.c
Expand Up @@ -311,16 +311,17 @@ socket_close(int code, Datum arg)
* specified. For TCP ports, hostName is either NULL for all interfaces or
* the interface to listen on, and unixSocketDir is ignored (can be NULL).
*
* Successfully opened sockets are added to the ListenSocket[] array (of
* length MaxListen), at the first position that isn't PGINVALID_SOCKET.
* Successfully opened sockets are appended to the ListenSockets[] array. On
* entry, *NumListenSockets holds the number of elements currently in the
* array, and it is updated to reflect the opened sockets. MaxListen is the
* allocated size of the array.
*
* RETURNS: STATUS_OK or STATUS_ERROR
*/

int
StreamServerPort(int family, const char *hostName, unsigned short portNumber,
const char *unixSocketDir,
pgsocket ListenSocket[], int MaxListen)
pgsocket ListenSockets[], int *NumListenSockets, int MaxListen)
{
pgsocket fd;
int err;
Expand All @@ -335,7 +336,6 @@ StreamServerPort(int family, const char *hostName, unsigned short portNumber,
struct addrinfo *addrs = NULL,
*addr;
struct addrinfo hint;
int listen_index = 0;
int added = 0;
char unixSocketPath[MAXPGPATH];
#if !defined(WIN32) || defined(IPV6_V6ONLY)
Expand Down Expand Up @@ -401,12 +401,7 @@ StreamServerPort(int family, const char *hostName, unsigned short portNumber,
}

/* See if there is still room to add 1 more socket. */
for (; listen_index < MaxListen; listen_index++)
{
if (ListenSocket[listen_index] == PGINVALID_SOCKET)
break;
}
if (listen_index >= MaxListen)
if (*NumListenSockets == MaxListen)
{
ereport(LOG,
(errmsg("could not bind to all requested addresses: MAXLISTEN (%d) exceeded",
Expand Down Expand Up @@ -573,7 +568,8 @@ StreamServerPort(int family, const char *hostName, unsigned short portNumber,
(errmsg("listening on %s address \"%s\", port %d",
familyDesc, addrDesc, (int) portNumber)));

ListenSocket[listen_index] = fd;
ListenSockets[*NumListenSockets] = fd;
(*NumListenSockets)++;
added++;
}

Expand Down
79 changes: 31 additions & 48 deletions src/backend/postmaster/postmaster.c
Expand Up @@ -227,7 +227,8 @@ int ReservedConnections;

/* The socket(s) we're listening to. */
#define MAXLISTEN 64
static pgsocket ListenSocket[MAXLISTEN];
static int NumListenSockets = 0;
static pgsocket *ListenSockets = NULL;

/* still more option variables */
bool EnableSSL = false;
Expand Down Expand Up @@ -588,7 +589,6 @@ PostmasterMain(int argc, char *argv[])
int status;
char *userDoption = NULL;
bool listen_addr_saved = false;
int i;
char *output_config_variable = NULL;

InitProcessGlobals();
Expand Down Expand Up @@ -1142,17 +1142,6 @@ PostmasterMain(int argc, char *argv[])
errmsg("could not remove file \"%s\": %m",
LOG_METAINFO_DATAFILE)));

/*
* Initialize input sockets.
*
* Mark them all closed, and set up an on_proc_exit function that's
* charged with closing the sockets again at postmaster shutdown.
*/
for (i = 0; i < MAXLISTEN; i++)
ListenSocket[i] = PGINVALID_SOCKET;

on_proc_exit(CloseServerPorts, 0);

/*
* If enabled, start up syslogger collection subprocess
*/
Expand Down Expand Up @@ -1187,7 +1176,13 @@ PostmasterMain(int argc, char *argv[])

/*
* Establish input sockets.
*
* First set up an on_proc_exit function that's charged with closing the
* sockets again at postmaster shutdown.
*/
ListenSockets = palloc(MAXLISTEN * sizeof(pgsocket));
on_proc_exit(CloseServerPorts, 0);

if (ListenAddresses)
{
char *rawstring;
Expand Down Expand Up @@ -1216,12 +1211,16 @@ PostmasterMain(int argc, char *argv[])
status = StreamServerPort(AF_UNSPEC, NULL,
(unsigned short) PostPortNumber,
NULL,
ListenSocket, MAXLISTEN);
ListenSockets,
&NumListenSockets,
MAXLISTEN);
else
status = StreamServerPort(AF_UNSPEC, curhost,
(unsigned short) PostPortNumber,
NULL,
ListenSocket, MAXLISTEN);
ListenSockets,
&NumListenSockets,
MAXLISTEN);

if (status == STATUS_OK)
{
Expand Down Expand Up @@ -1249,7 +1248,7 @@ PostmasterMain(int argc, char *argv[])

#ifdef USE_BONJOUR
/* Register for Bonjour only if we opened TCP socket(s) */
if (enable_bonjour && ListenSocket[0] != PGINVALID_SOCKET)
if (enable_bonjour && NumListenSockets > 0)
{
DNSServiceErrorType err;

Expand Down Expand Up @@ -1313,7 +1312,9 @@ PostmasterMain(int argc, char *argv[])
status = StreamServerPort(AF_UNIX, NULL,
(unsigned short) PostPortNumber,
socketdir,
ListenSocket, MAXLISTEN);
ListenSockets,
&NumListenSockets,
MAXLISTEN);

if (status == STATUS_OK)
{
Expand All @@ -1339,7 +1340,7 @@ PostmasterMain(int argc, char *argv[])
/*
* check that we have some socket to listen on
*/
if (ListenSocket[0] == PGINVALID_SOCKET)
if (NumListenSockets == 0)
ereport(FATAL,
(errmsg("no socket created for listening")));

Expand Down Expand Up @@ -1487,14 +1488,9 @@ CloseServerPorts(int status, Datum arg)
* before we remove the postmaster.pid lockfile; otherwise there's a race
* condition if a new postmaster wants to re-use the TCP port number.
*/
for (i = 0; i < MAXLISTEN; i++)
{
if (ListenSocket[i] != PGINVALID_SOCKET)
{
StreamClose(ListenSocket[i]);
ListenSocket[i] = PGINVALID_SOCKET;
}
}
for (i = 0; i < NumListenSockets; i++)
StreamClose(ListenSockets[i]);
NumListenSockets = 0;

/*
* Next, remove any filesystem entries for Unix sockets. To avoid race
Expand Down Expand Up @@ -1695,29 +1691,19 @@ DetermineSleepTime(void)
static void
ConfigurePostmasterWaitSet(bool accept_connections)
{
int nsockets;

if (pm_wait_set)
FreeWaitEventSet(pm_wait_set);
pm_wait_set = NULL;

/* How many server sockets do we need to wait for? */
nsockets = 0;
if (accept_connections)
{
while (nsockets < MAXLISTEN &&
ListenSocket[nsockets] != PGINVALID_SOCKET)
++nsockets;
}

pm_wait_set = CreateWaitEventSet(CurrentMemoryContext, 1 + nsockets);
pm_wait_set = CreateWaitEventSet(CurrentMemoryContext,
accept_connections ? (1 + NumListenSockets) : 1);
AddWaitEventToSet(pm_wait_set, WL_LATCH_SET, PGINVALID_SOCKET, MyLatch,
NULL);

if (accept_connections)
{
for (int i = 0; i < nsockets; i++)
AddWaitEventToSet(pm_wait_set, WL_SOCKET_ACCEPT, ListenSocket[i],
for (int i = 0; i < NumListenSockets; i++)
AddWaitEventToSet(pm_wait_set, WL_SOCKET_ACCEPT, ListenSockets[i],
NULL, NULL);
}
}
Expand Down Expand Up @@ -2579,14 +2565,11 @@ ClosePostmasterPorts(bool am_syslogger)
* EXEC_BACKEND mode.
*/
#ifndef EXEC_BACKEND
for (int i = 0; i < MAXLISTEN; i++)
{
if (ListenSocket[i] != PGINVALID_SOCKET)
{
StreamClose(ListenSocket[i]);
ListenSocket[i] = PGINVALID_SOCKET;
}
}
for (int i = 0; i < NumListenSockets; i++)
StreamClose(ListenSockets[i]);
NumListenSockets = 0;
pfree(ListenSockets);
ListenSockets = NULL;
#endif

/*
Expand Down
2 changes: 1 addition & 1 deletion src/include/libpq/libpq.h
Expand Up @@ -66,7 +66,7 @@ extern PGDLLIMPORT WaitEventSet *FeBeWaitSet;

extern int StreamServerPort(int family, const char *hostName,
unsigned short portNumber, const char *unixSocketDir,
pgsocket ListenSocket[], int MaxListen);
pgsocket ListenSocket[], int *NumListenSockets, int MaxListen);
extern int StreamConnection(pgsocket server_fd, Port *port);
extern void StreamClose(pgsocket sock);
extern void TouchSocketFiles(void);
Expand Down

0 comments on commit e29c464

Please sign in to comment.