aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/postmaster/postmaster.c44
-rw-r--r--src/backend/utils/init/globals.c9
-rw-r--r--src/backend/utils/misc/guc.c30
-rw-r--r--src/include/postmaster/postmaster.h9
4 files changed, 52 insertions, 40 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 73bacd89bcc..fa5aeed31db 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -499,6 +499,7 @@ typedef struct
bool redirection_done;
bool IsBinaryUpgrade;
int max_safe_fds;
+ int MaxBackends;
#ifdef WIN32
HANDLE PostmasterHandle;
HANDLE initial_signal_pipe;
@@ -897,15 +898,14 @@ PostmasterMain(int argc, char *argv[])
process_shared_preload_libraries();
/*
- * If loadable modules have added background workers, MaxBackends needs to
- * be updated. Do so now by forcing a no-op update of max_connections.
- * XXX This is a pretty ugly way to do it, but it doesn't seem worth
- * introducing a new entry point in guc.c to do it in a cleaner fashion.
+ * Now that loadable modules have had their chance to register background
+ * workers, calculate MaxBackends. Add one for the autovacuum launcher.
*/
- if (GetNumShmemAttachedBgworkers() > 0)
- SetConfigOption("max_connections",
- GetConfigOption("max_connections", false, false),
- PGC_POSTMASTER, PGC_S_OVERRIDE);
+ MaxBackends = MaxConnections + autovacuum_max_workers + 1 +
+ GetNumShmemAttachedBgworkers();
+ /* internal error because the values were all checked previously */
+ if (MaxBackends > MAX_BACKENDS)
+ elog(ERROR, "too many backends configured");
/*
* Establish input sockets.
@@ -5152,6 +5152,8 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
{
RegisteredBgWorker *rw;
int namelen = strlen(worker->bgw_name);
+ static int maxworkers;
+ static int numworkers = 0;
#ifdef EXEC_BACKEND
@@ -5162,6 +5164,11 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
static int BackgroundWorkerCookie = 1;
#endif
+ /* initialize upper limit on first call */
+ if (numworkers == 0)
+ maxworkers = MAX_BACKENDS -
+ (MaxConnections + autovacuum_max_workers + 1);
+
if (!IsUnderPostmaster)
ereport(LOG,
(errmsg("registering background worker: %s", worker->bgw_name)));
@@ -5215,6 +5222,23 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
}
/*
+ * Enforce maximum number of workers. Note this is overly restrictive:
+ * we could allow more non-shmem-connected workers, because these don't
+ * count towards the MAX_BACKENDS limit elsewhere. This doesn't really
+ * matter for practical purposes; several million processes would need to
+ * run on a single server.
+ */
+ if (++numworkers > maxworkers)
+ {
+ ereport(LOG,
+ (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
+ errmsg("too many background workers"),
+ errdetail("Up to %d background workers can be registered with the current settings.",
+ maxworkers)));
+ return;
+ }
+
+ /*
* Copy the registration data into the registered workers list.
*/
rw = malloc(sizeof(RegisteredBgWorker) + namelen + 1);
@@ -5836,6 +5860,8 @@ save_backend_variables(BackendParameters *param, Port *port,
param->IsBinaryUpgrade = IsBinaryUpgrade;
param->max_safe_fds = max_safe_fds;
+ param->MaxBackends = MaxBackends;
+
#ifdef WIN32
param->PostmasterHandle = PostmasterHandle;
if (!write_duplicated_handle(&param->initial_signal_pipe,
@@ -6061,6 +6087,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
IsBinaryUpgrade = param->IsBinaryUpgrade;
max_safe_fds = param->max_safe_fds;
+ MaxBackends = param->MaxBackends;
+
#ifdef WIN32
PostmasterHandle = param->PostmasterHandle;
pgwin32_initial_signal_pipe = param->initial_signal_pipe;
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 00288530c07..f1f8b177f35 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -103,13 +103,14 @@ int work_mem = 1024;
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):
+ * Primary determinants of sizes of shared-memory structures.
+ *
+ * MaxBackends is computed by PostmasterMain after modules have had a chance to
+ * register background workers.
*/
int NBuffers = 1000;
-int MaxBackends = 100;
int MaxConnections = 90;
+int MaxBackends = 0;
int VacuumCostPageHit = 1; /* GUC parameters for vacuum */
int VacuumCostPageMiss = 10;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index d91924cc234..ac5e4f3e48d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -103,17 +103,6 @@
#define MAX_KILOBYTES (INT_MAX / 1024)
#endif
-/*
- * Note: MAX_BACKENDS is limited to 2^23-1 because inval.c stores the
- * backend ID as a 3-byte signed integer. Even if that limitation were
- * removed, we still could not exceed INT_MAX/4 because some places compute
- * 4*MaxBackends without any overflow check. This is rechecked in
- * check_maxconnections, since MaxBackends is computed as MaxConnections
- * plus the number of bgworkers plus autovacuum_max_workers plus one (for the
- * autovacuum launcher).
- */
-#define MAX_BACKENDS 0x7fffff
-
#define KB_PER_MB (1024)
#define KB_PER_GB (1024*1024)
@@ -199,9 +188,7 @@ static const char *show_tcp_keepalives_idle(void);
static const char *show_tcp_keepalives_interval(void);
static const char *show_tcp_keepalives_count(void);
static bool check_maxconnections(int *newval, void **extra, GucSource source);
-static void assign_maxconnections(int newval, void *extra);
static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource source);
-static void assign_autovacuum_max_workers(int newval, void *extra);
static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
static void assign_effective_io_concurrency(int newval, void *extra);
static void assign_pgstat_temp_directory(const char *newval, void *extra);
@@ -1615,7 +1602,7 @@ static struct config_int ConfigureNamesInt[] =
},
&MaxConnections,
100, 1, MAX_BACKENDS,
- check_maxconnections, assign_maxconnections, NULL
+ check_maxconnections, NULL, NULL
},
{
@@ -2290,7 +2277,7 @@ static struct config_int ConfigureNamesInt[] =
},
&autovacuum_max_workers,
3, 1, MAX_BACKENDS,
- check_autovacuum_max_workers, assign_autovacuum_max_workers, NULL
+ check_autovacuum_max_workers, NULL, NULL
},
{
@@ -8636,13 +8623,6 @@ check_maxconnections(int *newval, void **extra, GucSource source)
return true;
}
-static void
-assign_maxconnections(int newval, void *extra)
-{
- MaxBackends = newval + autovacuum_max_workers + 1 +
- GetNumShmemAttachedBgworkers();
-}
-
static bool
check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
{
@@ -8652,12 +8632,6 @@ check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
return true;
}
-static void
-assign_autovacuum_max_workers(int newval, void *extra)
-{
- MaxBackends = MaxConnections + newval + 1 + GetNumShmemAttachedBgworkers();
-}
-
static bool
check_effective_io_concurrency(int *newval, void **extra, GucSource source)
{
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index eaca868b008..8b2d5b913e3 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -61,4 +61,13 @@ extern Size ShmemBackendArraySize(void);
extern void ShmemBackendArrayAllocation(void);
#endif
+/*
+ * Note: MAX_BACKENDS is limited to 2^23-1 because inval.c stores the
+ * backend ID as a 3-byte signed integer. Even if that limitation were
+ * removed, we still could not exceed INT_MAX/4 because some places compute
+ * 4*MaxBackends without any overflow check. This is rechecked in the relevant
+ * GUC check hooks and in RegisterBackgroundWorker().
+ */
+#define MAX_BACKENDS 0x7fffff
+
#endif /* _POSTMASTER_H */