Remove check hooks for GUCs that contribute to MaxBackends.
authorNathan Bossart <[email protected]>
Fri, 5 Jul 2024 19:42:55 +0000 (14:42 -0500)
committerNathan Bossart <[email protected]>
Fri, 5 Jul 2024 19:42:55 +0000 (14:42 -0500)
Each of max_connections, max_worker_processes,
autovacuum_max_workers, and max_wal_senders has a GUC check hook
that verifies the sum of those GUCs does not exceed a hard-coded
limit (see the comment for MAX_BACKENDS in postmaster.h).  In
general, the hooks effectively guard against egregious
misconfigurations.

However, this approach has some problems.  Since these check hooks
are called as each GUC is assigned its user-specified value, only
one of the hooks will be called with all the relevant GUCs set.  If
one or more of the user-specified values are less than the initial
values of the GUCs' underlying variables, false positives can
occur.

Furthermore, the error message emitted when one of the check hooks
fails is not tremendously helpful.  For example, the command

$ pg_ctl -D . start -o "-c max_connections=262100 -c max_wal_senders=10000"

fails with the following error:

FATAL:  invalid value for parameter "max_wal_senders": 10000

Fortunately, there is an extra copy of this check in
InitializeMaxBackends() that we can rely on, so this commit removes
the aforementioned GUC check hooks in favor of that one.  It also
enhances the error message to clearly show the values of the
relevant GUCs and the hard-coded limit their sum may not exceed.
The downside of this change is that server startup progresses
further before failing due to such misconfigurations (thus taking
longer), but these failures are expected to be rare, so we don't
anticipate any real harm in practice.

Reviewed-by: Tom Lane
Discussion: https://postgr.es/m/ZnMr2k-Nk5vj7T7H%40nathan

src/backend/utils/init/postinit.c
src/backend/utils/misc/guc_tables.c
src/include/utils/guc_hooks.h

index 0805398e24df10616f8efd5bfc8a7759c04b3730..25867c8bd5b960c28e9089641b356834b25318a9 100644 (file)
@@ -580,57 +580,14 @@ InitializeMaxBackends(void)
    MaxBackends = MaxConnections + autovacuum_max_workers + 1 +
        max_worker_processes + max_wal_senders;
 
-   /* internal error because the values were all checked previously */
    if (MaxBackends > MAX_BACKENDS)
-       elog(ERROR, "too many backends configured");
-}
-
-/*
- * GUC check_hook for max_connections
- */
-bool
-check_max_connections(int *newval, void **extra, GucSource source)
-{
-   if (*newval + autovacuum_max_workers + 1 +
-       max_worker_processes + max_wal_senders > MAX_BACKENDS)
-       return false;
-   return true;
-}
-
-/*
- * GUC check_hook for autovacuum_max_workers
- */
-bool
-check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
-{
-   if (MaxConnections + *newval + 1 +
-       max_worker_processes + max_wal_senders > MAX_BACKENDS)
-       return false;
-   return true;
-}
-
-/*
- * GUC check_hook for max_worker_processes
- */
-bool
-check_max_worker_processes(int *newval, void **extra, GucSource source)
-{
-   if (MaxConnections + autovacuum_max_workers + 1 +
-       *newval + max_wal_senders > MAX_BACKENDS)
-       return false;
-   return true;
-}
-
-/*
- * GUC check_hook for max_wal_senders
- */
-bool
-check_max_wal_senders(int *newval, void **extra, GucSource source)
-{
-   if (MaxConnections + autovacuum_max_workers + 1 +
-       max_worker_processes + *newval > MAX_BACKENDS)
-       return false;
-   return true;
+       ereport(ERROR,
+               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                errmsg("too many server processes configured"),
+                errdetail("\"max_connections\" (%d) plus \"autovacuum_max_workers\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.",
+                          MaxConnections, autovacuum_max_workers,
+                          max_worker_processes, max_wal_senders,
+                          MAX_BACKENDS)));
 }
 
 /*
index d28b0bcb40057791d958698f13f401df7dff419f..630ed0f1629f92ca5ccf3b49a8e0561b277243e0 100644 (file)
@@ -2209,7 +2209,7 @@ struct config_int ConfigureNamesInt[] =
        },
        &MaxConnections,
        100, 1, MAX_BACKENDS,
-       check_max_connections, NULL, NULL
+       NULL, NULL, NULL
    },
 
    {
@@ -2925,7 +2925,7 @@ struct config_int ConfigureNamesInt[] =
        },
        &max_wal_senders,
        10, 0, MAX_BACKENDS,
-       check_max_wal_senders, NULL, NULL
+       NULL, NULL, NULL
    },
 
    {
@@ -3155,7 +3155,7 @@ struct config_int ConfigureNamesInt[] =
        },
        &max_worker_processes,
        8, 0, MAX_BACKENDS,
-       check_max_worker_processes, NULL, NULL
+       NULL, NULL, NULL
    },
 
    {
@@ -3389,7 +3389,7 @@ struct config_int ConfigureNamesInt[] =
        },
        &autovacuum_max_workers,
        3, 1, MAX_BACKENDS,
-       check_autovacuum_max_workers, NULL, NULL
+       NULL, NULL, NULL
    },
 
    {
index 070d3f2a1ad053dca6be5d275e0a491fd17dce37..153c652c93ed984e2b921888ebebbc58ff2b9943 100644 (file)
@@ -29,8 +29,6 @@ extern bool check_application_name(char **newval, void **extra,
                                   GucSource source);
 extern void assign_application_name(const char *newval, void *extra);
 extern const char *show_archive_command(void);
-extern bool check_autovacuum_max_workers(int *newval, void **extra,
-                                        GucSource source);
 extern bool check_autovacuum_work_mem(int *newval, void **extra,
                                      GucSource source);
 extern bool check_vacuum_buffer_usage_limit(int *newval, void **extra,
@@ -84,13 +82,9 @@ extern const char *show_log_timezone(void);
 extern bool check_maintenance_io_concurrency(int *newval, void **extra,
                                             GucSource source);
 extern void assign_maintenance_io_concurrency(int newval, void *extra);
-extern bool check_max_connections(int *newval, void **extra, GucSource source);
-extern bool check_max_wal_senders(int *newval, void **extra, GucSource source);
 extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
                                         GucSource source);
 extern void assign_max_wal_size(int newval, void *extra);
-extern bool check_max_worker_processes(int *newval, void **extra,
-                                      GucSource source);
 extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
 extern void assign_max_stack_depth(int newval, void *extra);
 extern bool check_multixact_member_buffers(int *newval, void **extra,