Skip to content

Commit 0c39c29

Browse files
committed
Support "postgres -C" with runtime-computed GUCs
Until now, the -C option of postgres was handled before a small subset of GUCs computed at runtime are initialized, leading to incorrect results as GUC machinery would fall back to default values for such parameters. For example, data_checksums could report "off" for a cluster as the control file is not loaded yet. Or wal_segment_size would show a segment size at 16MB even if initdb --wal-segsize used something else. Worse, the command would fail to properly report the recently-introduced shared_memory, that requires to load shared_preload_libraries as these could ask for a chunk of shared memory. Support for runtime GUCs comes with a limitation, as the operation is now allowed on a running server. One notable reason for this is that _PG_init() functions of loadable libraries are called before all runtime-computed GUCs are initialized, and this is not guaranteed to be safe to do on running servers. For the case of shared_memory_size, where we want to know how much memory would be used without allocating it, this limitation is fine. Another case where this will help is for huge pages, with the introduction of a different GUC to evaluate the amount of huge pages required for a server before starting it, without having to allocate large chunks of memory. This feature is controlled with a new GUC flag, and four parameters are classified as runtime-computed as of this change: - data_checksums - shared_memory_size - data_directory_mode - wal_segment_size Some TAP tests are added to provide some coverage here, using data_checksums in the tests of pg_checksums. Per discussion with Andres Freund, Justin Pryzby, Magnus Hagander and more. Author: Nathan Bossart Discussion: https://postgr.es/m/F2772387-CE0F-46BF-B5F1-CC55516EB885@amazon.com
1 parent 2c7615f commit 0c39c29

File tree

5 files changed

+83
-14
lines changed

5 files changed

+83
-14
lines changed

doc/src/sgml/ref/postgres-ref.sgml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,20 @@ PostgreSQL documentation
133133
<listitem>
134134
<para>
135135
Prints the value of the named run-time parameter, and exits.
136-
(See the <option>-c</option> option above for details.) This can
137-
be used on a running server, and returns values from
136+
(See the <option>-c</option> option above for details.) This
137+
returns values from
138138
<filename>postgresql.conf</filename>, modified by any parameters
139139
supplied in this invocation. It does not reflect parameters
140140
supplied when the cluster was started.
141141
</para>
142142

143+
<para>
144+
This can be used on a running server for most parameters. However,
145+
the server must be shut down for some runtime-computed parameters
146+
(e.g., <xref linkend="guc-shared-memory-size"/> and
147+
<xref linkend="guc-wal-segment-size"/>).
148+
</para>
149+
143150
<para>
144151
This option is meant for other programs that interact with a server
145152
instance, such as <xref linkend="app-pg-ctl"/>, to query configuration

src/backend/postmaster/postmaster.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -896,15 +896,31 @@ PostmasterMain(int argc, char *argv[])
896896
if (output_config_variable != NULL)
897897
{
898898
/*
899-
* "-C guc" was specified, so print GUC's value and exit. No extra
900-
* permission check is needed because the user is reading inside the
901-
* data dir.
899+
* If this is a runtime-computed GUC, it hasn't yet been initialized,
900+
* and the present value is not useful. However, this is a convenient
901+
* place to print the value for most GUCs because it is safe to run
902+
* postmaster startup to this point even if the server is already
903+
* running. For the handful of runtime-computed GUCs that we cannot
904+
* provide meaningful values for yet, we wait until later in
905+
* postmaster startup to print the value. We won't be able to use -C
906+
* on running servers for those GUCs, but using this option now would
907+
* lead to incorrect results for them.
902908
*/
903-
const char *config_val = GetConfigOption(output_config_variable,
904-
false, false);
909+
int flags = GetConfigOptionFlags(output_config_variable, true);
905910

906-
puts(config_val ? config_val : "");
907-
ExitPostmaster(0);
911+
if ((flags & GUC_RUNTIME_COMPUTED) == 0)
912+
{
913+
/*
914+
* "-C guc" was specified, so print GUC's value and exit. No
915+
* extra permission check is needed because the user is reading
916+
* inside the data dir.
917+
*/
918+
const char *config_val = GetConfigOption(output_config_variable,
919+
false, false);
920+
921+
puts(config_val ? config_val : "");
922+
ExitPostmaster(0);
923+
}
908924
}
909925

910926
/* Verify that DataDir looks reasonable */
@@ -1033,6 +1049,26 @@ PostmasterMain(int argc, char *argv[])
10331049
*/
10341050
InitializeShmemGUCs();
10351051

1052+
/*
1053+
* If -C was specified with a runtime-computed GUC, we held off printing
1054+
* the value earlier, as the GUC was not yet initialized. We handle -C
1055+
* for most GUCs before we lock the data directory so that the option may
1056+
* be used on a running server. However, a handful of GUCs are runtime-
1057+
* computed and do not have meaningful values until after locking the data
1058+
* directory, and we cannot safely calculate their values earlier on a
1059+
* running server. At this point, such GUCs should be properly
1060+
* initialized, and we haven't yet set up shared memory, so this is a good
1061+
* time to handle the -C option for these special GUCs.
1062+
*/
1063+
if (output_config_variable != NULL)
1064+
{
1065+
const char *config_val = GetConfigOption(output_config_variable,
1066+
false, false);
1067+
1068+
puts(config_val ? config_val : "");
1069+
ExitPostmaster(0);
1070+
}
1071+
10361072
/*
10371073
* Set up shared memory and semaphores.
10381074
*/

src/backend/utils/misc/guc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,7 +1983,7 @@ static struct config_bool ConfigureNamesBool[] =
19831983
{"data_checksums", PGC_INTERNAL, PRESET_OPTIONS,
19841984
gettext_noop("Shows whether data checksums are turned on for this cluster."),
19851985
NULL,
1986-
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
1986+
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
19871987
},
19881988
&data_checksums,
19891989
false,
@@ -2342,7 +2342,7 @@ static struct config_int ConfigureNamesInt[] =
23422342
{"shared_memory_size", PGC_INTERNAL, PRESET_OPTIONS,
23432343
gettext_noop("Shows the size of the server's main shared memory area (rounded up to the nearest MB)."),
23442344
NULL,
2345-
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_UNIT_MB
2345+
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_UNIT_MB | GUC_RUNTIME_COMPUTED
23462346
},
23472347
&shared_memory_size_mb,
23482348
0, 0, INT_MAX,
@@ -2407,7 +2407,7 @@ static struct config_int ConfigureNamesInt[] =
24072407
"in the form accepted by the chmod and umask system "
24082408
"calls. (To use the customary octal format the number "
24092409
"must start with a 0 (zero).)"),
2410-
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
2410+
GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
24112411
},
24122412
&data_directory_mode,
24132413
0700, 0000, 0777,
@@ -3231,7 +3231,7 @@ static struct config_int ConfigureNamesInt[] =
32313231
{"wal_segment_size", PGC_INTERNAL, PRESET_OPTIONS,
32323232
gettext_noop("Shows the size of write ahead log segments."),
32333233
NULL,
3234-
GUC_UNIT_BYTE | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
3234+
GUC_UNIT_BYTE | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
32353235
},
32363236
&wal_segment_size,
32373237
DEFAULT_XLOG_SEG_SIZE,

src/bin/pg_checksums/t/002_actions.pl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use TestLib;
1111

1212
use Fcntl qw(:seek);
13-
use Test::More tests => 63;
13+
use Test::More tests => 69;
1414

1515

1616
# Utility routine to create and check a table with corrupted checksums
@@ -178,11 +178,31 @@ sub check_relation_corruption
178178
[ 'pg_checksums', '--enable', '--filenode', '1234', '-D', $pgdata ],
179179
"fails when relfilenodes are requested and action is --enable");
180180

181+
# Test postgres -C for an offline cluster.
182+
# Run-time GUCs are safe to query here. Note that a lock file is created,
183+
# then unlinked, leading to an extra LOG entry showing in stderr.
184+
command_checks_all(
185+
[ 'postgres', '-D', $pgdata, '-C', 'data_checksums' ],
186+
0,
187+
[qr/^on$/],
188+
# LOG entry when unlinking lock file.
189+
[qr/database system is shut down/],
190+
'data_checksums=on is reported on an offline cluster');
191+
181192
# Checks cannot happen with an online cluster
182193
$node->start;
183194
command_fails([ 'pg_checksums', '--check', '-D', $pgdata ],
184195
"fails with online cluster");
185196

197+
# Test postgres -C on an online cluster.
198+
command_fails_like(
199+
[ 'postgres', '-D', $pgdata, '-C', 'data_checksums' ],
200+
qr/lock file .* already exists/,
201+
'data_checksums is not reported on an online cluster');
202+
command_ok(
203+
[ 'postgres', '-D', $pgdata, '-C', 'work_mem' ],
204+
'non-runtime parameter is reported on an online cluster');
205+
186206
# Check corruption of table on default tablespace.
187207
check_relation_corruption($node, 'corrupt1', 'pg_default');
188208

src/include/utils/guc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ typedef enum
229229

230230
#define GUC_EXPLAIN 0x100000 /* include in explain */
231231

232+
/*
233+
* GUC_RUNTIME_COMPUTED is intended for runtime-computed GUCs that are only
234+
* available via 'postgres -C' if the server is not running.
235+
*/
236+
#define GUC_RUNTIME_COMPUTED 0x200000
237+
232238
#define GUC_UNIT (GUC_UNIT_MEMORY | GUC_UNIT_TIME)
233239

234240

0 commit comments

Comments
 (0)