*** a/src/backend/postmaster/postmaster.c --- b/src/backend/postmaster/postmaster.c *************** *** 162,175 **** char *ListenAddresses; /* * ReservedBackends is the number of backends reserved for superuser use. ! * This number is taken out of the pool size given by MaxBackends so ! * number of backend slots available to non-superusers is ! * (MaxBackends - ReservedBackends). Note what this really means is ! * "if there are <= ReservedBackends connections available, only superusers ! * can make new connections" --- pre-existing superuser connections don't ! * count against the limit. */ ! int ReservedBackends; /* The socket(s) we're listening to. */ #define MAXLISTEN 64 --- 162,177 ---- /* * ReservedBackends is the number of backends reserved for superuser use. ! * This number is ReservedConnections + max_wal_senders (it is computed by ! * the GUC assign hooks for those variables) and taken out of the pool size ! * given by MaxBackends so number of backend slots available to ! * non-superusers is (MaxBackends - ReservedBackends). Note what this ! * really means is "if there are <= ReservedBackends connections available, ! * only superusers can make new connections" --- pre-existing superuser ! * connections don't count against the limit. */ ! int ReservedBackends = 3; ! int ReservedConnections = 3; /* The socket(s) we're listening to. */ #define MAXLISTEN 64 *** a/src/backend/storage/lmgr/proc.c --- b/src/backend/storage/lmgr/proc.c *************** *** 142,149 **** ProcGlobalSemas(void) * running out when trying to start another backend is a common failure. * So, now we grab enough semaphores to support the desired max number * of backends immediately at initialization --- if the sysadmin has set ! * MaxConnections or autovacuum_max_workers higher than his kernel will ! * support, he'll find out sooner rather than later. * * Another reason for creating semaphores here is that the semaphore * implementation typically requires us to create semaphores in the --- 142,149 ---- * running out when trying to start another backend is a common failure. * So, now we grab enough semaphores to support the desired max number * of backends immediately at initialization --- if the sysadmin has set ! * MaxConnections, autovacuum_max_workers, or max_wal_senders higher ! * than his kernel will support, he'll find out sooner rather than later. * * Another reason for creating semaphores here is that the semaphore * implementation typically requires us to create semaphores in the *************** *** 158,163 **** InitProcGlobal(void) --- 158,164 ---- { PGPROC *procs; int i; + int numconn; bool found; /* Create the ProcGlobal shared structure */ *************** *** 185,197 **** InitProcGlobal(void) /* * Pre-create the PGPROC structures and create a semaphore for each. */ ! procs = (PGPROC *) ShmemAlloc((MaxConnections) * sizeof(PGPROC)); if (!procs) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); ! MemSet(procs, 0, MaxConnections * sizeof(PGPROC)); ! for (i = 0; i < MaxConnections; i++) { PGSemaphoreCreate(&(procs[i].sem)); procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs; --- 186,199 ---- /* * Pre-create the PGPROC structures and create a semaphore for each. */ ! numconn = MaxConnections + max_wal_senders; ! procs = (PGPROC *) ShmemAlloc((numconn) * sizeof(PGPROC)); if (!procs) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); ! MemSet(procs, 0, numconn * sizeof(PGPROC)); ! for (i = 0; i < numconn; i++) { PGSemaphoreCreate(&(procs[i].sem)); procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs; *** a/src/backend/utils/init/globals.c --- b/src/backend/utils/init/globals.c *************** *** 100,107 **** int maintenance_work_mem = 16384; /* * Primary determinants of sizes of shared-memory structures. MaxBackends is ! * MaxConnections + autovacuum_max_workers + 1 (it is computed by the GUC ! * assign hooks for those variables): */ int NBuffers = 1000; int MaxBackends = 100; --- 100,107 ---- /* * Primary determinants of sizes of shared-memory structures. MaxBackends is ! * MaxConnections + autovacuum_max_workers + 1 + max_wal_senders (it is ! * computed by the GUC assign hooks for those variables): */ int NBuffers = 1000; int MaxBackends = 100; *** a/src/backend/utils/misc/guc.c --- b/src/backend/utils/misc/guc.c *************** *** 172,178 **** static const char *show_tcp_keepalives_idle(void); --- 172,180 ---- static const char *show_tcp_keepalives_interval(void); static const char *show_tcp_keepalives_count(void); static bool assign_maxconnections(int newval, bool doit, GucSource source); + static bool assign_reserved_connections(int newval, bool doit, GucSource source); static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source); + static bool assign_max_wal_senders(int newval, bool doit, GucSource source); static bool assign_effective_io_concurrency(int newval, bool doit, GucSource source); static const char *assign_pgstat_temp_directory(const char *newval, bool doit, GucSource source); static const char *assign_application_name(const char *newval, bool doit, GucSource source); *************** *** 1361,1367 **** static struct config_int ConfigureNamesInt[] = * Note: MaxBackends is limited to INT_MAX/4 because some places compute * 4*MaxBackends without any overflow check. This check is made in * assign_maxconnections, since MaxBackends is computed as MaxConnections ! * plus autovacuum_max_workers plus one (for the autovacuum launcher). * * Likewise we have to limit NBuffers to INT_MAX/2. * --- 1363,1370 ---- * Note: MaxBackends is limited to INT_MAX/4 because some places compute * 4*MaxBackends without any overflow check. This check is made in * assign_maxconnections, since MaxBackends is computed as MaxConnections ! * plus autovacuum_max_workers plus one (for the autovacuum launcher) ! * plus max_wal_senders. * * Likewise we have to limit NBuffers to INT_MAX/2. * *************** *** 1390,1397 **** static struct config_int ConfigureNamesInt[] = gettext_noop("Sets the number of connection slots reserved for superusers."), NULL }, ! &ReservedBackends, ! 3, 0, INT_MAX / 4, NULL, NULL }, { --- 1393,1400 ---- gettext_noop("Sets the number of connection slots reserved for superusers."), NULL }, ! &ReservedConnections, ! 3, 0, INT_MAX / 4, assign_reserved_connections, NULL }, { *************** *** 1706,1712 **** static struct config_int ConfigureNamesInt[] = NULL }, &max_wal_senders, ! 0, 0, INT_MAX / 4, NULL, NULL }, { --- 1709,1715 ---- NULL }, &max_wal_senders, ! 0, 0, INT_MAX / 4, assign_max_wal_senders, NULL }, { *************** *** 7819,7829 **** show_tcp_keepalives_count(void) static bool assign_maxconnections(int newval, bool doit, GucSource source) { ! if (newval + autovacuum_max_workers + 1 > INT_MAX / 4) return false; if (doit) ! MaxBackends = newval + autovacuum_max_workers + 1; return true; } --- 7822,7844 ---- static bool assign_maxconnections(int newval, bool doit, GucSource source) { ! if (newval + autovacuum_max_workers + 1 + max_wal_senders > INT_MAX / 4) return false; if (doit) ! MaxBackends = newval + autovacuum_max_workers + 1 + max_wal_senders; ! ! return true; ! } ! ! static bool ! assign_reserved_connections(int newval, bool doit, GucSource source) ! { ! if (newval + max_wal_senders > INT_MAX / 4) ! return false; ! ! if (doit) ! ReservedBackends = newval + max_wal_senders; return true; } *************** *** 7831,7841 **** assign_maxconnections(int newval, bool doit, GucSource source) static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source) { ! if (MaxConnections + newval + 1 > INT_MAX / 4) return false; if (doit) ! MaxBackends = MaxConnections + newval + 1; return true; } --- 7846,7872 ---- static bool assign_autovacuum_max_workers(int newval, bool doit, GucSource source) { ! if (MaxConnections + newval + 1 + max_wal_senders > INT_MAX / 4) return false; if (doit) ! MaxBackends = MaxConnections + newval + 1 + max_wal_senders; ! ! return true; ! } ! ! static bool ! assign_max_wal_senders(int newval, bool doit, GucSource source) ! { ! if (MaxConnections + autovacuum_max_workers + 1 + newval > INT_MAX / 4 || ! ReservedConnections + newval > INT_MAX / 4) ! return false; ! ! if (doit) ! { ! MaxBackends = MaxConnections + autovacuum_max_workers + 1 + newval; ! ReservedBackends = ReservedConnections + newval; ! } return true; } *** a/src/include/postmaster/postmaster.h --- b/src/include/postmaster/postmaster.h *************** *** 17,22 **** --- 17,23 ---- extern bool EnableSSL; extern bool SilentMode; extern int ReservedBackends; + extern int ReservedConnections; extern int PostPortNumber; extern int Unix_socket_permissions; extern char *Unix_socket_group;