diff options
Diffstat (limited to 'src/backend/utils/init/postinit.c')
-rw-r--r-- | src/backend/utils/init/postinit.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 5b9ed2f6f52..ca53912f151 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -25,6 +25,7 @@ #include "access/session.h" #include "access/sysattr.h" #include "access/tableam.h" +#include "access/twophase.h" #include "access/xact.h" #include "access/xlog.h" #include "access/xloginsert.h" @@ -65,6 +66,9 @@ #include "utils/syscache.h" #include "utils/timeout.h" +static int MaxBackends = 0; +static int MaxBackendsInitialized = false; + static HeapTuple GetDatabaseTuple(const char *dbname); static HeapTuple GetDatabaseTupleByOid(Oid dboid); static void PerformAuthentication(Port *port); @@ -495,15 +499,49 @@ pg_split_opts(char **argv, int *argcp, const char *optstr) void InitializeMaxBackends(void) { - Assert(MaxBackends == 0); - /* the extra unit accounts for the autovacuum launcher */ - MaxBackends = MaxConnections + autovacuum_max_workers + 1 + - max_worker_processes + max_wal_senders; + SetMaxBackends(MaxConnections + autovacuum_max_workers + 1 + + max_worker_processes + max_wal_senders); +} + +/* + * Safely retrieve the value of MaxBackends. + * + * Previously, MaxBackends was externally visible, but it was often used before + * it was initialized (e.g., in preloaded libraries' _PG_init() functions). + * Unfortunately, we cannot initialize MaxBackends before processing + * shared_preload_libraries because the libraries sometimes alter GUCs that are + * used to calculate its value. Instead, we provide this function for accessing + * MaxBackends, and we ERROR if someone calls it before it is initialized. + */ +int +GetMaxBackends(void) +{ + if (unlikely(!MaxBackendsInitialized)) + elog(ERROR, "MaxBackends not yet initialized"); + + return MaxBackends; +} + +/* + * Set the value of MaxBackends. + * + * This should only be used by InitializeMaxBackends() and + * restore_backend_variables(). If MaxBackends is already initialized or the + * specified value is greater than the maximum, this will ERROR. + */ +void +SetMaxBackends(int max_backends) +{ + if (MaxBackendsInitialized) + elog(ERROR, "MaxBackends already initialized"); /* internal error because the values were all checked previously */ - if (MaxBackends > MAX_BACKENDS) + if (max_backends > MAX_BACKENDS) elog(ERROR, "too many backends configured"); + + MaxBackends = max_backends; + MaxBackendsInitialized = true; } /* @@ -609,7 +647,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, SharedInvalBackendInit(false); - if (MyBackendId > MaxBackends || MyBackendId <= 0) + if (MyBackendId > GetMaxBackends() || MyBackendId <= 0) elog(FATAL, "bad backend ID: %d", MyBackendId); /* Now that we have a BackendId, we can participate in ProcSignal */ |