From 7bde686796bd7b8db22d89f8164f1120647f1bc3 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Fri, 30 Oct 2020 12:17:45 +0900 Subject: [PATCH] standby clone: handle missing "postgresql.auto.conf" In PostgreSQL 12 and later we need to append replication configuration to "postgresql.auto.conf" to guarantee it will be read last, and hence override any preceding replication configuration which may be haunting the configuration files. We've been assuming that "postgresql.auto.conf" will always be present, but at least one corner case has been observed where that was not the case on the node being cloned from. Moreover it's perfectly acceptable that this file does not exist (it will be recreated the next time ALTER SYSTEM is executed), so we should be prepared to handle that case. In passing, improve handling of more unlikely errors which might be encountered when processing "postgresql.auto.conf". --- HISTORY | 1 + configfile-scan.l | 4 ++-- configfile.c | 40 ++++++++++++++++++++++++++++++++-------- configfile.h | 2 +- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/HISTORY b/HISTORY index 523d12e3..abdaad9b 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,6 @@ 5.2.1 2020-??-?? config: fix parsing of "replication_type" + standby clone: handle missing "postgresql.auto.conf" 5.2.0 2020-10-22 general: add support for PostgreSQL 13 (Ian) diff --git a/configfile-scan.l b/configfile-scan.l index 3d157b29..59e7178f 100644 --- a/configfile-scan.l +++ b/configfile-scan.l @@ -107,9 +107,9 @@ ProcessRepmgrConfigFile(const char *config_file, const char *base_dir, ItemList extern bool -ProcessPostgresConfigFile(const char *config_file, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) +ProcessPostgresConfigFile(const char *config_file, const char *base_dir, bool strict, KeyValueList *contents, ItemList *error_list, ItemList *warning_list) { - return ProcessConfigFile(base_dir, config_file, NULL, true, 0, contents, error_list, warning_list); + return ProcessConfigFile(base_dir, config_file, NULL, strict, 0, contents, error_list, warning_list); } static bool diff --git a/configfile.c b/configfile.c index 81985dd4..83f2a0c4 100644 --- a/configfile.c +++ b/configfile.c @@ -1785,7 +1785,7 @@ modify_auto_conf(const char *data_dir, KeyValueList *items) FILE *fp; mode_t um; - struct stat auto_conf_st; + struct stat data_dir_st; KeyValueList config = {NULL, NULL}; KeyValueListCell *cell = NULL; @@ -1796,7 +1796,12 @@ modify_auto_conf(const char *data_dir, KeyValueList *items) appendPQExpBuffer(&auto_conf, "%s/%s", data_dir, PG_AUTOCONF_FILENAME); - success = ProcessPostgresConfigFile(auto_conf.data, NULL, &config, NULL, NULL); + success = ProcessPostgresConfigFile(auto_conf.data, + NULL, + false, /* we don't care if the file does not exist */ + &config, + NULL, + NULL); if (success == false) { @@ -1807,7 +1812,7 @@ modify_auto_conf(const char *data_dir, KeyValueList *items) } /* - * Append requested items to items extracted from the existing file. + * Append requested items to any items extracted from the existing file. */ for (cell = items->head; cell; cell = cell->next) { @@ -1836,27 +1841,46 @@ modify_auto_conf(const char *data_dir, KeyValueList *items) cell->key, cell->value); } - stat(auto_conf.data, &auto_conf_st); + /* stat the data directory for the file mode */ + if (stat(data_dir, &data_dir_st) != 0) + { + /* + * This is highly unlikely to happen, but if it does (e.g. freak + * race condition with some rogue process which is messing about + * with the data directory), there's not a lot we can do. + */ + log_error(_("error encountered when checking \"%s\""), + data_dir); + log_detail("%s", strerror(errno)); + exit(ERR_BAD_CONFIG); + } /* - * Set umask so the temporary file is created in the same mode as the original - * postgresql.auto.conf file. + * Set umask so the temporary file is created in the same mode as the data + * directory. In PostgreSQL 11 and later this can be 0700 or 0750. */ - um = umask(~(auto_conf_st.st_mode)); + um = umask(~(data_dir_st.st_mode)); + fp = fopen(auto_conf_tmp.data, "w"); + umask(um); if (fp == NULL) { - fprintf(stderr, "unable to open \"%s\": %s\n", + fprintf(stderr, "unable to open \"%s\" for writing: %s\n", auto_conf_tmp.data, strerror(errno)); + success = false; } else { if (fwrite(auto_conf_contents.data, strlen(auto_conf_contents.data), 1, fp) != 1) { + fprintf(stderr, "unable to write to \"%s\": %s\n", + auto_conf_tmp.data, + strerror(errno)); fclose(fp); + success = false; } else { diff --git a/configfile.h b/configfile.h index 20e29731..4c8f9742 100644 --- a/configfile.h +++ b/configfile.h @@ -373,6 +373,6 @@ extern bool modify_auto_conf(const char *data_dir, KeyValueList *items); extern bool ProcessRepmgrConfigFile(const char *config_file, const char *base_dir, ItemList *error_list, ItemList *warning_list); -extern bool ProcessPostgresConfigFile(const char *config_file, const char *base_dir, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); +extern bool ProcessPostgresConfigFile(const char *config_file, const char *base_dir, bool strict, KeyValueList *contents, ItemList *error_list, ItemList *warning_list); #endif /* _REPMGR_CONFIGFILE_H_ */