/* Function headers */
static void usage(void);
-static void disconnect_and_exit(int code) pg_attribute_noreturn();
static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found);
static void progress_report(int tablespacenum, const char *filename, bool force);
}
static void
-disconnect_and_exit(int code)
+disconnect_atexit(void)
{
if (conn != NULL)
PQfinish(conn);
+}
#ifndef WIN32
-
- /*
- * On windows, our background thread dies along with the process. But on
- * Unix, if we have started a subprocess, we want to kill it off so it
- * doesn't remain running trying to stream data.
- */
+/*
+ * On windows, our background thread dies along with the process. But on
+ * Unix, if we have started a subprocess, we want to kill it off so it
+ * doesn't remain running trying to stream data.
+ */
+static void
+kill_bgchild_atexit(void)
+{
if (bgchild > 0)
kill(bgchild, SIGTERM);
-#endif
-
- exit(code);
}
-
+#endif
/*
* Split argument into old_dir and new_dir and append to tablespace mapping
fprintf(stderr,
_("%s: could not parse write-ahead log location \"%s\"\n"),
progname, startpos);
- disconnect_and_exit(1);
+ exit(1);
}
param->startptr = ((uint64) hi) << 32 | lo;
/* Round off to even segment position */
fprintf(stderr,
_("%s: could not create pipe for background process: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
#endif
{
if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL,
temp_replication_slot, true, true, false))
- disconnect_and_exit(1);
+ exit(1);
if (verbose)
{
fprintf(stderr,
_("%s: could not create directory \"%s\": %s\n"),
progname, statusdir, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
{
fprintf(stderr, _("%s: could not create background process: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
/*
* Else we are in the parent process and all is well.
*/
+ atexit(kill_bgchild_atexit);
#else /* WIN32 */
bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
if (bgchild == 0)
{
fprintf(stderr, _("%s: could not create background thread: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
#endif
}
fprintf(stderr,
_("%s: could not create directory \"%s\": %s\n"),
progname, dirname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (created)
*created = true;
fprintf(stderr,
_("%s: directory \"%s\" exists but is not empty\n"),
progname, dirname);
- disconnect_and_exit(1);
+ exit(1);
case -1:
/*
*/
fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
progname, dirname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
fprintf(stderr,
_("%s: could not write to compressed file \"%s\": %s\n"),
progname, current_file, get_gz_error(ztarfile));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
{
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
progname, current_file, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
}
fprintf(stderr,
_("%s: could not set compression level %d: %s\n"),
progname, compresslevel, get_gz_error(ztarfile));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
fprintf(stderr,
_("%s: could not set compression level %d: %s\n"),
progname, compresslevel, get_gz_error(ztarfile));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
fprintf(stderr,
_("%s: could not set compression level %d: %s\n"),
progname, compresslevel, get_gz_error(ztarfile));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
fprintf(stderr,
_("%s: could not create compressed file \"%s\": %s\n"),
progname, filename, get_gz_error(ztarfile));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
{
fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
{
fprintf(stderr, _("%s: could not get COPY data stream: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
while (1)
fprintf(stderr,
_("%s: could not close compressed file \"%s\": %s\n"),
progname, filename, get_gz_error(ztarfile));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
fprintf(stderr,
_("%s: could not close file \"%s\": %s\n"),
progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
}
{
fprintf(stderr, _("%s: could not read COPY data: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
if (!writerecoveryconf || !basetablespace)
{
fprintf(stderr, _("%s: could not get COPY data stream: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
while (1)
{
fprintf(stderr, _("%s: could not read COPY data: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
if (file == NULL)
{
fprintf(stderr, _("%s: invalid tar block header size: %d\n"),
progname, r);
- disconnect_and_exit(1);
+ exit(1);
}
totaldone += 512;
fprintf(stderr,
_("%s: could not create directory \"%s\": %s\n"),
progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
#ifndef WIN32
_("%s: could not create symbolic link from \"%s\" to \"%s\": %s\n"),
progname, filename, mapped_tblspc_path,
strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
else
fprintf(stderr,
_("%s: unrecognized link indicator \"%c\"\n"),
progname, copybuf[156]);
- disconnect_and_exit(1);
+ exit(1);
}
continue; /* directory or link handled */
}
{
fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
#ifndef WIN32
{
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
totaldone += r;
progress_report(rownum, filename, false);
fprintf(stderr,
_("%s: COPY stream ended before last file was finished\n"),
progname);
- disconnect_and_exit(1);
+ exit(1);
}
if (copybuf != NULL)
if (!recoveryconfcontents)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
- disconnect_and_exit(1);
+ exit(1);
}
connOptions = PQconninfo(conn);
if (connOptions == NULL)
{
fprintf(stderr, _("%s: out of memory\n"), progname);
- disconnect_and_exit(1);
+ exit(1);
}
initPQExpBuffer(&conninfo_buf);
PQExpBufferDataBroken(conninfo_buf))
{
fprintf(stderr, _("%s: out of memory\n"), progname);
- disconnect_and_exit(1);
+ exit(1);
}
termPQExpBuffer(&conninfo_buf);
if (cf == NULL)
{
fprintf(stderr, _("%s: could not open file \"%s\": %s\n"), progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (fwrite(recoveryconfcontents->data, recoveryconfcontents->len, 1, cf) != 1)
fprintf(stderr,
_("%s: could not write to file \"%s\": %s\n"),
progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
fclose(cf);
if (cf == NULL)
{
fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
fclose(cf);
fprintf(stderr, _("%s: incompatible server version %s\n"),
progname, serverver ? serverver : "'unknown'");
- disconnect_and_exit(1);
+ exit(1);
}
/*
* but add a hint about using -X none.
*/
fprintf(stderr, _("HINT: use -X none or -X fetch to disable log streaming\n"));
- disconnect_and_exit(1);
+ exit(1);
}
/*
* Run IDENTIFY_SYSTEM so we can get the timeline
*/
if (!RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL))
- disconnect_and_exit(1);
+ exit(1);
/*
* Start the actual backup
{
fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
progname, "BASE_BACKUP", PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
/*
{
fprintf(stderr, _("%s: could not initiate base backup: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
if (PQntuples(res) != 1)
{
fprintf(stderr,
_("%s: server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields\n"),
progname, PQntuples(res), PQnfields(res), 1, 2);
- disconnect_and_exit(1);
+ exit(1);
}
strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
{
fprintf(stderr, _("%s: could not get backup header: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
if (PQntuples(res) < 1)
{
fprintf(stderr, _("%s: no data returned from server\n"), progname);
- disconnect_and_exit(1);
+ exit(1);
}
/*
fprintf(stderr,
_("%s: can only write single tablespace to stdout, database has %d\n"),
progname, PQntuples(res));
- disconnect_and_exit(1);
+ exit(1);
}
/*
fprintf(stderr,
_("%s: could not get write-ahead log end position from server: %s"),
progname, PQerrorMessage(conn));
- disconnect_and_exit(1);
+ exit(1);
}
if (PQntuples(res) != 1)
{
fprintf(stderr,
_("%s: no write-ahead log end position returned from server\n"),
progname);
- disconnect_and_exit(1);
+ exit(1);
}
strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
if (verbose && includewal != NO_WAL)
fprintf(stderr, _("%s: final receive failed: %s"),
progname, PQerrorMessage(conn));
}
- disconnect_and_exit(1);
+ exit(1);
}
if (bgchild > 0)
fprintf(stderr,
_("%s: could not send command to background pipe: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
/* Just wait for the background process to exit */
{
fprintf(stderr, _("%s: could not wait for child process: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (r != bgchild)
{
fprintf(stderr, _("%s: child %d died, expected %d\n"),
progname, (int) r, (int) bgchild);
- disconnect_and_exit(1);
+ exit(1);
}
if (status != 0)
{
fprintf(stderr, "%s: %s\n",
progname, wait_result_to_str(status));
- disconnect_and_exit(1);
+ exit(1);
}
/* Exited normally, we're happy! */
#else /* WIN32 */
fprintf(stderr,
_("%s: could not parse write-ahead log location \"%s\"\n"),
progname, xlogend);
- disconnect_and_exit(1);
+ exit(1);
}
xlogendptr = ((uint64) hi) << 32 | lo;
InterlockedIncrement(&has_xlogendptr);
_dosmaperr(GetLastError());
fprintf(stderr, _("%s: could not wait for child thread: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (GetExitCodeThread((HANDLE) bgchild_handle, &status) == 0)
{
_dosmaperr(GetLastError());
fprintf(stderr, _("%s: could not get child thread exit status: %s\n"),
progname, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (status != 0)
{
fprintf(stderr, _("%s: child thread exited with error %u\n"),
progname, (unsigned int) status);
- disconnect_and_exit(1);
+ exit(1);
}
/* Exited normally, we're happy */
#endif
*/
PQclear(res);
PQfinish(conn);
+ conn = NULL;
/*
* Make data persistent on disk once backup is completed. For tar format
/* Error message already written in GetConnection() */
exit(1);
}
+ atexit(disconnect_atexit);
/*
* Set umask so that directories/files are created with the same
/* determine remote server's xlog segment size */
if (!RetrieveWalSegSize(conn))
- disconnect_and_exit(1);
+ exit(1);
/* Create pg_wal symlink, if required */
if (xlog_dir)
{
fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"),
progname, linkloc, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
#else
fprintf(stderr, _("%s: symlinks are not supported on this platform\n"), progname);
- disconnect_and_exit(1);
+ exit(1);
#endif
free(linkloc);
}
static bool stop_streaming(XLogRecPtr segendpos, uint32 timeline,
bool segment_finished);
-#define disconnect_and_exit(code) \
- { \
- if (conn != NULL) PQfinish(conn); \
- exit(code); \
- }
+static void
+disconnect_atexit(void)
+{
+ if (conn != NULL)
+ PQfinish(conn);
+}
/* Routines to evaluate segment file format */
#define IsCompressXLogFileName(fname) \
{
fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
progname, basedir, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
return dir;
{
fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
progname, dest_folder, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
}
{
fprintf(stderr, _("%s: could not stat file \"%s\": %s\n"),
progname, fullpath, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (statbuf.st_size != WalSegSz)
{
fprintf(stderr, _("%s: could not open compressed file \"%s\": %s\n"),
progname, fullpath, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
if (lseek(fd, (off_t) (-4), SEEK_END) < 0)
{
fprintf(stderr, _("%s: could not seek in compressed file \"%s\": %s\n"),
progname, fullpath, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
r = read(fd, (char *) buf, sizeof(buf));
if (r != sizeof(buf))
else
fprintf(stderr, _("%s: could not read compressed file \"%s\": read %d of %zu\n"),
progname, fullpath, r, sizeof(buf));
- disconnect_and_exit(1);
+ exit(1);
}
close(fd);
{
fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
progname, basedir, strerror(errno));
- disconnect_and_exit(1);
+ exit(1);
}
close_destination_dir(dir, basedir);
* There's no hope of recovering from a version mismatch, so don't
* retry.
*/
- disconnect_and_exit(1);
+ exit(1);
}
/*
* existing output directory.
*/
if (!RunIdentifySystem(conn, NULL, &servertli, &serverpos, NULL))
- disconnect_and_exit(1);
+ exit(1);
/*
* Figure out where to start streaming.
}
PQfinish(conn);
+ conn = NULL;
FreeWalDirectoryMethod();
pg_free(stream.walmethod);
if (!conn)
/* error message already written in GetConnection() */
exit(1);
+ atexit(disconnect_atexit);
/*
* Run IDENTIFY_SYSTEM to make sure we've successfully have established a
* connection.
*/
if (!RunIdentifySystem(conn, NULL, NULL, NULL, &db_name))
- disconnect_and_exit(1);
+ exit(1);
/*
* Set umask so that directories/files are created with the same
/* determine remote server's xlog segment size */
if (!RetrieveWalSegSize(conn))
- disconnect_and_exit(1);
+ exit(1);
/*
* Check that there is a database associated with connection, none should
fprintf(stderr,
_("%s: replication connection using slot \"%s\" is unexpectedly database specific\n"),
progname, replication_slot);
- disconnect_and_exit(1);
+ exit(1);
}
/*
progname, replication_slot);
if (!DropReplicationSlot(conn, replication_slot))
- disconnect_and_exit(1);
- disconnect_and_exit(0);
+ exit(1);
+ exit(0);
}
/* Create a replication slot */
if (!CreateReplicationSlot(conn, replication_slot, NULL, false, true, false,
slot_exists_ok))
- disconnect_and_exit(1);
- disconnect_and_exit(0);
+ exit(1);
+ exit(0);
}
/*