diff --git a/doc/src/sgml/ref/pg_receivexlog.sgml b/doc/src/sgml/ref/pg_receivexlog.sgml index 8e5fca4022..f0a7763bdf 100644 --- a/doc/src/sgml/ref/pg_receivexlog.sgml +++ b/doc/src/sgml/ref/pg_receivexlog.sgml @@ -58,6 +58,14 @@ PostgreSQL documentation configured with set high enough to leave at least one session available for the stream. + + + If the connection is lost, or if it cannot be initially established, + with a non-fatal error, pg_receivexlog will + retry the connection indefinitely, and reestablish streaming as soon + as possible. To avoid this behavior, use the -n + parameter. + @@ -86,6 +94,17 @@ PostgreSQL documentation The following command-line options control the running of the program. + + + + + + Don't loop on connection errors. Instead, exit right away with + an error. + + + + diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index 6a2e557809..d7466168d7 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -279,6 +279,9 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier) /* Get a second connection */ param->bgconn = GetConnection(); + if (!param->bgconn) + /* Error message already written in GetConnection() */ + exit(1); /* * Always in plain format, so we can write to basedir/pg_xlog. But the @@ -915,6 +918,9 @@ BaseBackup(void) * Connect in replication mode to the server */ conn = GetConnection(); + if (!conn) + /* Error message already written in GetConnection() */ + exit(1); /* * Run IDENTIFY_SYSTEM so we can get the timeline diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c index 01f20f372a..084ddc4a8c 100644 --- a/src/bin/pg_basebackup/pg_receivexlog.c +++ b/src/bin/pg_basebackup/pg_receivexlog.c @@ -33,9 +33,13 @@ #include "getopt_long.h" +/* Time to sleep between reconnection attempts */ +#define RECONNECT_SLEEP_TIME 5 + /* Global options */ char *basedir = NULL; int verbose = 0; +int noloop = 0; int standby_message_timeout = 10; /* 10 sec = default */ volatile bool time_to_abort = false; @@ -55,6 +59,7 @@ usage(void) printf(_("\nOptions controlling the output:\n")); printf(_(" -D, --dir=directory receive xlog files into this directory\n")); printf(_("\nGeneral options:\n")); + printf(_(" -n, --noloop do not loop on connection lost\n")); printf(_(" -v, --verbose output verbose messages\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_(" -V, --version output version information, then exit\n")); @@ -214,6 +219,9 @@ StreamLog(void) * Connect in replication mode to the server */ conn = GetConnection(); + if (!conn) + /* Error message already written in GetConnection() */ + return; /* * Run IDENTIFY_SYSTEM so we can get the timeline and current xlog @@ -289,6 +297,7 @@ main(int argc, char **argv) {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, + {"noloop", no_argument, NULL, 'n'}, {"no-password", no_argument, NULL, 'w'}, {"password", no_argument, NULL, 'W'}, {"statusint", required_argument, NULL, 's'}, @@ -317,7 +326,7 @@ main(int argc, char **argv) } } - while ((c = getopt_long(argc, argv, "D:h:p:U:s:wWv", + while ((c = getopt_long(argc, argv, "D:h:p:U:s:nwWv", long_options, &option_index)) != -1) { switch (c) @@ -355,6 +364,9 @@ main(int argc, char **argv) exit(1); } break; + case 'n': + noloop = 1; + break; case 'v': verbose++; break; @@ -397,7 +409,28 @@ main(int argc, char **argv) pqsignal(SIGINT, sigint_handler); #endif - StreamLog(); + while (true) + { + StreamLog(); + if (time_to_abort) + /* + * We've been Ctrl-C'ed. That's not an error, so exit without + * an errorcode. + */ + exit(0); + else if (noloop) + { + fprintf(stderr, _("%s: disconnected.\n"), progname); + exit(1); + } + else + { + fprintf(stderr, _("%s: disconnected. Waiting %d seconds to try again\n"), + progname, RECONNECT_SLEEP_TIME); + pg_usleep(RECONNECT_SLEEP_TIME * 1000000); + } + } - exit(0); + /* Never get here */ + exit(2); } diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c index cc015370ff..1416faa2e3 100644 --- a/src/bin/pg_basebackup/streamutil.c +++ b/src/bin/pg_basebackup/streamutil.c @@ -65,6 +65,11 @@ xmalloc0(int size) } +/* + * Connect to the server. Returns a valid PGconn pointer if connected, + * or NULL on non-permanent error. On permanent error, the function will + * call exit(1) directly. + */ PGconn * GetConnection(void) { @@ -151,7 +156,7 @@ GetConnection(void) { fprintf(stderr, _("%s: could not connect to server: %s\n"), progname, PQerrorMessage(tmpconn)); - exit(1); + return NULL; } /* Connection ok! */