diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 8d217b06455d4..522584e5978a1 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -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; @@ -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) @@ -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", @@ -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++; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 54e9bfb8c487a..0d876c61fd70d 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -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; @@ -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(); @@ -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 */ @@ -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; @@ -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) { @@ -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; @@ -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) { @@ -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"))); @@ -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 @@ -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); } } @@ -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 /* diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index 50fc781f471f3..a6104d8cd02bb 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -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);