diff options
author | Bruce Momjian <bruce@momjian.us> | 2018-07-28 15:01:55 -0400 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2018-07-28 15:01:55 -0400 |
commit | 260fe9f2b02b67de1e5ff29faf123e4220586c43 (patch) | |
tree | be33655c5c4055bb4170d1c2a0761d5ca9e4ffba | |
parent | cda8e1182727bb09d77c6ec42bb4abf5ba27d2bb (diff) | |
download | postgresql-260fe9f2b02b67de1e5ff29faf123e4220586c43.tar.gz |
pg_upgrade: check for clean server shutdowns
Previously pg_upgrade checked for the pid file and started/stopped the
server to force a clean shutdown. However, "pg_ctl -m immediate"
removes the pid file but doesn't do a clean shutdown, so check
pg_controldata for a clean shutdown too.
Diagnosed-by: Vimalraj A
Discussion: https://postgr.es/m/CAFKBAK5e4Q-oTUuPPJ56EU_d2Rzodq6GWKS3ncAk3xo7hAsOZg@mail.gmail.com
Backpatch-through: 9.3
-rw-r--r-- | src/bin/pg_upgrade/controldata.c | 59 | ||||
-rw-r--r-- | src/bin/pg_upgrade/pg_upgrade.c | 3 |
2 files changed, 61 insertions, 1 deletions
diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index dcbad611f3..c189fa845f 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -58,6 +58,7 @@ get_control_data(ClusterInfo *cluster, bool live_check) bool got_large_object = false; bool got_date_is_int = false; bool got_data_checksum_version = false; + bool got_cluster_state = false; char *lc_collate = NULL; char *lc_ctype = NULL; char *lc_monetary = NULL; @@ -405,6 +406,64 @@ get_control_data(ClusterInfo *cluster, bool live_check) pclose(output); /* + * Check for clean shutdown + */ + + /* only pg_controldata outputs the cluster state */ + snprintf(cmd, sizeof(cmd), "\"%s/pg_controldata\" \"%s\"", + cluster->bindir, cluster->pgdata); + fflush(stdout); + fflush(stderr); + + if ((output = popen(cmd, "r")) == NULL) + pg_fatal("could not get control data using %s: %s\n", + cmd, strerror(errno)); + + /* we have the result of cmd in "output". so parse it line by line now */ + while (fgets(bufin, sizeof(bufin), output)) + { + if ((!live_check || cluster == &new_cluster) && + (p = strstr(bufin, "Database cluster state:")) != NULL) + { + p = strchr(p, ':'); + + if (p == NULL || strlen(p) <= 1) + pg_fatal("%d: database cluster state problem\n", __LINE__); + + p++; /* remove ':' char */ + + /* + * We checked earlier for a postmaster lock file, and if we found + * one, we tried to start/stop the server to replay the WAL. However, + * pg_ctl -m immediate doesn't leave a lock file, but does require + * WAL replay, so we check here that the server was shut down cleanly, + * from the controldata perspective. + */ + /* remove leading spaces */ + while (*p == ' ') + p++; + if (strcmp(p, "shut down\n") != 0) + { + if (cluster == &old_cluster) + pg_fatal("The source cluster was not shut down cleanly.\n"); + else + pg_fatal("The target cluster was not shut down cleanly.\n"); + } + got_cluster_state = true; + } + } + + pclose(output); + + if (!got_cluster_state) + { + if (cluster == &old_cluster) + pg_fatal("The source cluster lacks cluster state information:\n"); + else + pg_fatal("The target cluster lacks cluster state information:\n"); + } + + /* * Restore environment variables */ pg_putenv("LC_COLLATE", lc_collate); diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 551e6cc5f8..c2a775a3e4 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -201,7 +201,8 @@ setup(char *argv0, bool *live_check) * start, assume the server is running. If the pid file is left over * from a server crash, this also allows any committed transactions * stored in the WAL to be replayed so they are not lost, because WAL - * files are not transferred from old to new servers. + * files are not transferred from old to new servers. We later check + * for a clean shutdown. */ if (start_postmaster(&old_cluster, false)) stop_postmaster(false); |