diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c
index c30b8f97380cf06125adbc1bcb9334cf0105f47c..ff8e714074f513d996d632c26ad494a2da34be62 100644
--- a/src/bin/pg_dump/compress_io.c
+++ b/src/bin/pg_dump/compress_io.c
@@ -256,8 +256,8 @@ EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs)
 	DeflateCompressorZlib(AH, cs, true);
 
 	if (deflateEnd(zp) != Z_OK)
-		die_horribly(AH, modulename,
-					 "could not close compression stream: %s\n", zp->msg);
+		exit_horribly(modulename,
+					  "could not close compression stream: %s\n", zp->msg);
 
 	free(cs->zlibOut);
 	free(cs->zp);
@@ -274,8 +274,8 @@ DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush)
 	{
 		res = deflate(zp, flush ? Z_FINISH : Z_NO_FLUSH);
 		if (res == Z_STREAM_ERROR)
-			die_horribly(AH, modulename,
-						 "could not compress data: %s\n", zp->msg);
+			exit_horribly(modulename,
+						  "could not compress data: %s\n", zp->msg);
 		if ((flush && (zp->avail_out < cs->zlibOutSize))
 			|| (zp->avail_out == 0)
 			|| (zp->avail_in != 0)
@@ -295,9 +295,9 @@ DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush)
 				size_t		len = cs->zlibOutSize - zp->avail_out;
 
 				if (cs->writeF(AH, out, len) != len)
-					die_horribly(AH, modulename,
-								 "could not write to output file: %s\n",
-								 strerror(errno));
+					exit_horribly(modulename,
+								  "could not write to output file: %s\n",
+								  strerror(errno));
 			}
 			zp->next_out = (void *) out;
 			zp->avail_out = cs->zlibOutSize;
@@ -318,7 +318,7 @@ WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs,
 
 	/*
 	 * we have either succeeded in writing dLen bytes or we have called
-	 * die_horribly()
+	 * exit_horribly()
 	 */
 	return dLen;
 }
@@ -361,8 +361,8 @@ ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF)
 
 			res = inflate(zp, 0);
 			if (res != Z_OK && res != Z_STREAM_END)
-				die_horribly(AH, modulename,
-							 "could not uncompress data: %s\n", zp->msg);
+				exit_horribly(modulename,
+							  "could not uncompress data: %s\n", zp->msg);
 
 			out[ZLIB_OUT_SIZE - zp->avail_out] = '\0';
 			ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH);
@@ -377,16 +377,16 @@ ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF)
 		zp->avail_out = ZLIB_OUT_SIZE;
 		res = inflate(zp, 0);
 		if (res != Z_OK && res != Z_STREAM_END)
-			die_horribly(AH, modulename,
-						 "could not uncompress data: %s\n", zp->msg);
+			exit_horribly(modulename,
+						  "could not uncompress data: %s\n", zp->msg);
 
 		out[ZLIB_OUT_SIZE - zp->avail_out] = '\0';
 		ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH);
 	}
 
 	if (inflateEnd(zp) != Z_OK)
-		die_horribly(AH, modulename,
-					 "could not close compression library: %s\n", zp->msg);
+		exit_horribly(modulename,
+					  "could not close compression library: %s\n", zp->msg);
 
 	free(buf);
 	free(out);
@@ -426,9 +426,9 @@ WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs,
 	 * do a check here as well...
 	 */
 	if (cs->writeF(AH, data, dLen) != dLen)
-		die_horribly(AH, modulename,
-					 "could not write to output file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename,
+					  "could not write to output file: %s\n",
+					  strerror(errno));
 	return dLen;
 }
 
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 0b24220bd46180054b56661d1817142c55f473b6..8f70259415787b321498dea09465d146ed6f4486 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -49,6 +49,7 @@ static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
 #ifdef WIN32
 static bool parallel_init_done = false;
 static DWORD tls_index;
+static DWORD mainThreadId;
 #endif
 
 void
@@ -59,6 +60,7 @@ init_parallel_dump_utils(void)
 	{
 		tls_index = TlsAlloc();
 		parallel_init_done = true;
+		mainThreadId = GetCurrentThreadId();
 	}
 #endif
 }
@@ -1320,5 +1322,9 @@ exit_nicely(int code)
 	while (--on_exit_nicely_index >= 0)
 		(*on_exit_nicely_list[on_exit_nicely_index].function)(code,
 			on_exit_nicely_list[on_exit_nicely_index].arg);
+#ifdef WIN32
+	if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
+		ExitThread(code);
+#endif
 	exit(code);
 }
diff --git a/src/bin/pg_dump/nls.mk b/src/bin/pg_dump/nls.mk
index b1b4a0e175255a71aa20e9ae4d9f035a63ebcda9..6ba25d338d95a4e55c29e2fcb3492422a656f775 100644
--- a/src/bin/pg_dump/nls.mk
+++ b/src/bin/pg_dump/nls.mk
@@ -2,13 +2,13 @@
 CATALOG_NAME     = pg_dump
 AVAIL_LANGUAGES  = de es fr it ja ko pt_BR sv tr zh_CN zh_TW
 GETTEXT_FILES    = pg_dump.c common.c pg_backup_archiver.c pg_backup_custom.c \
-                   pg_backup_db.c pg_backup_files.c pg_backup_null.c \
+                   pg_backup_db.c pg_backup_null.c \
                    pg_backup_tar.c pg_restore.c pg_dumpall.c \
                    ../../port/exec.c
-GETTEXT_TRIGGERS = write_msg:2 die_horribly:3 exit_horribly:2 simple_prompt \
-                   ExecuteSqlCommand:3 ahlog:3
+GETTEXT_TRIGGERS = write_msg:2 exit_horribly:2 simple_prompt \
+                   ExecuteSqlCommand:3 ahlog:3 warn_or_exit_horribly:3
 GETTEXT_FLAGS  = \
     write_msg:2:c-format \
-    die_horribly:3:c-format \
     exit_horribly:2:c-format \
-    ahlog:3:c-format
+    ahlog:3:c-format \
+    warn_or_exit_horribly:3:c-format
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 927950caff23b1e7641d3e47722a7b0742ade1c8..e29265953d46aa9730eccca41062dfd9b2c45ba3 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -61,11 +61,28 @@
 #define thandle HANDLE
 #endif
 
+typedef struct ParallelStateEntry
+{
+#ifdef WIN32
+	unsigned int threadId;
+#else
+	pid_t		pid;
+#endif
+	ArchiveHandle *AH;
+} ParallelStateEntry;
+
+typedef struct ParallelState
+{
+	int			numWorkers;
+	ParallelStateEntry *pse;
+} ParallelState;
+
 /* Arguments needed for a worker child */
 typedef struct _restore_args
 {
 	ArchiveHandle *AH;
 	TocEntry   *te;
+	ParallelStateEntry *pse;
 } RestoreArgs;
 
 /* State for each parallel activity slot */
@@ -75,6 +92,14 @@ typedef struct _parallel_slot
 	RestoreArgs *args;
 } ParallelSlot;
 
+typedef struct ShutdownInformation
+{
+	ParallelState *pstate;
+	Archive       *AHX;
+} ShutdownInformation;
+
+static ShutdownInformation shutdown_info;
+
 #define NO_SLOT (-1)
 
 #define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
@@ -122,10 +147,6 @@ static int	_discoverArchiveFormat(ArchiveHandle *AH);
 
 static int	RestoringToDB(ArchiveHandle *AH);
 static void dump_lo_buf(ArchiveHandle *AH);
-static void vdie_horribly(ArchiveHandle *AH, const char *modulename,
-						  const char *fmt, va_list ap)
-	__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0), noreturn));
-
 static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
 static void SetOutput(ArchiveHandle *AH, const char *filename, int compression);
 static OutputContext SaveOutput(ArchiveHandle *AH);
@@ -160,6 +181,11 @@ static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te);
 static ArchiveHandle *CloneArchive(ArchiveHandle *AH);
 static void DeCloneArchive(ArchiveHandle *AH);
 
+static void setProcessIdentifier(ParallelStateEntry *pse, ArchiveHandle *AH);
+static void unsetProcessIdentifier(ParallelStateEntry *pse);
+static ParallelStateEntry *GetMyPSEntry(ParallelState *pstate);
+static void archive_close_connection(int code, void *arg);
+
 
 /*
  *	Wrapper functions.
@@ -208,8 +234,8 @@ CloseArchive(Archive *AHX)
 		res = fclose(AH->OF);
 
 	if (res != 0)
-		die_horribly(AH, modulename, "could not close output file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename, "could not close output file: %s\n",
+					  strerror(errno));
 }
 
 /* Public */
@@ -234,14 +260,14 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 	 * connected to, not the one we will create, which is very bad...
 	 */
 	if (ropt->createDB && ropt->dropSchema)
-		die_horribly(AH, modulename, "-C and -c are incompatible options\n");
+		exit_horribly(modulename, "-C and -c are incompatible options\n");
 
 	/*
 	 * -C is not compatible with -1, because we can't create a database inside
 	 * a transaction block.
 	 */
 	if (ropt->createDB && ropt->single_txn)
-		die_horribly(AH, modulename, "-C and -1 are incompatible options\n");
+		exit_horribly(modulename, "-C and -1 are incompatible options\n");
 
 	/*
 	 * If we're going to do parallel restore, there are some restrictions.
@@ -251,11 +277,11 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 	{
 		/* We haven't got round to making this work for all archive formats */
 		if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
-			die_horribly(AH, modulename, "parallel restore is not supported with this archive file format\n");
+			exit_horribly(modulename, "parallel restore is not supported with this archive file format\n");
 
 		/* Doesn't work if the archive represents dependencies as OIDs */
 		if (AH->version < K_VERS_1_8)
-			die_horribly(AH, modulename, "parallel restore is not supported with archives made by pre-8.0 pg_dump\n");
+			exit_horribly(modulename, "parallel restore is not supported with archives made by pre-8.0 pg_dump\n");
 
 		/*
 		 * It's also not gonna work if we can't reopen the input file, so
@@ -274,7 +300,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 		{
 			reqs = _tocEntryRequired(te, ropt, false);
 			if (te->hadDumper && (reqs & REQ_DATA) != 0)
-				die_horribly(AH, modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
+				exit_horribly(modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
 		}
 	}
 #endif
@@ -286,7 +312,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 	{
 		ahlog(AH, 1, "connecting to database for restore\n");
 		if (AH->version < K_VERS_1_3)
-			die_horribly(AH, modulename, "direct database connections are not supported in pre-1.3 archives\n");
+			exit_horribly(modulename, "direct database connections are not supported in pre-1.3 archives\n");
 
 		/* XXX Should get this from the archive */
 		AHX->minRemoteVersion = 070100;
@@ -734,7 +760,7 @@ WriteData(Archive *AHX, const void *data, size_t dLen)
 	ArchiveHandle *AH = (ArchiveHandle *) AHX;
 
 	if (!AH->currToc)
-		die_horribly(AH, modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
+		exit_horribly(modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
 
 	return (*AH->WriteDataPtr) (AH, data, dLen);
 }
@@ -886,7 +912,7 @@ StartBlob(Archive *AHX, Oid oid)
 	ArchiveHandle *AH = (ArchiveHandle *) AHX;
 
 	if (!AH->StartBlobPtr)
-		die_horribly(AH, modulename, "large-object output not supported in chosen format\n");
+		exit_horribly(modulename, "large-object output not supported in chosen format\n");
 
 	(*AH->StartBlobPtr) (AH, AH->currToc, oid);
 
@@ -973,13 +999,13 @@ StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
 		{
 			loOid = lo_create(AH->connection, oid);
 			if (loOid == 0 || loOid != oid)
-				die_horribly(AH, modulename, "could not create large object %u: %s",
-							 oid, PQerrorMessage(AH->connection));
+				exit_horribly(modulename, "could not create large object %u: %s",
+							  oid, PQerrorMessage(AH->connection));
 		}
 		AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
 		if (AH->loFd == -1)
-			die_horribly(AH, modulename, "could not open large object %u: %s",
-						 oid, PQerrorMessage(AH->connection));
+			exit_horribly(modulename, "could not open large object %u: %s",
+						  oid, PQerrorMessage(AH->connection));
 	}
 	else
 	{
@@ -1035,8 +1061,8 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
 	/* Setup the file */
 	fh = fopen(ropt->tocFile, PG_BINARY_R);
 	if (!fh)
-		die_horribly(AH, modulename, "could not open TOC file \"%s\": %s\n",
-					 ropt->tocFile, strerror(errno));
+		exit_horribly(modulename, "could not open TOC file \"%s\": %s\n",
+					  ropt->tocFile, strerror(errno));
 
 	incomplete_line = false;
 	while (fgets(buf, sizeof(buf), fh) != NULL)
@@ -1083,8 +1109,8 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
 		/* Find TOC entry */
 		te = getTocEntryByDumpId(AH, id);
 		if (!te)
-			die_horribly(AH, modulename, "could not find entry for ID %d\n",
-						 id);
+			exit_horribly(modulename, "could not find entry for ID %d\n",
+						  id);
 
 		/* Mark it wanted */
 		ropt->idWanted[id - 1] = true;
@@ -1104,8 +1130,8 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
 	}
 
 	if (fclose(fh) != 0)
-		die_horribly(AH, modulename, "could not close TOC file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename, "could not close TOC file: %s\n",
+					  strerror(errno));
 }
 
 /*
@@ -1221,11 +1247,11 @@ SetOutput(ArchiveHandle *AH, const char *filename, int compression)
 	if (!AH->OF)
 	{
 		if (filename)
-			die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
-						 filename, strerror(errno));
+			exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+						  filename, strerror(errno));
 		else
-			die_horribly(AH, modulename, "could not open output file: %s\n",
-						 strerror(errno));
+			exit_horribly(modulename, "could not open output file: %s\n",
+						  strerror(errno));
 	}
 }
 
@@ -1251,7 +1277,7 @@ RestoreOutput(ArchiveHandle *AH, OutputContext savedContext)
 		res = fclose(AH->OF);
 
 	if (res != 0)
-		die_horribly(AH, modulename, "could not close output file: %s\n",
+		exit_horribly(modulename, "could not close output file: %s\n",
 					 strerror(errno));
 
 	AH->gzOut = savedContext.gzOut;
@@ -1329,7 +1355,7 @@ dump_lo_buf(ArchiveHandle *AH)
 							  AH->lo_buf_used),
 			  (unsigned long) AH->lo_buf_used, (unsigned long) res);
 		if (res != AH->lo_buf_used)
-			die_horribly(AH, modulename,
+			exit_horribly(modulename,
 			"could not write to large object (result: %lu, expected: %lu)\n",
 					   (unsigned long) res, (unsigned long) AH->lo_buf_used);
 	}
@@ -1388,7 +1414,7 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
 	{
 		res = GZWRITE(ptr, size, nmemb, AH->OF);
 		if (res != (nmemb * size))
-			die_horribly(AH, modulename, "could not write to output file: %s\n", strerror(errno));
+			exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno));
 		return res;
 	}
 	else if (AH->CustomOutPtr)
@@ -1396,7 +1422,7 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
 		res = AH->CustomOutPtr (AH, ptr, size * nmemb);
 
 		if (res != (nmemb * size))
-			die_horribly(AH, modulename, "could not write to custom output routine\n");
+			exit_horribly(modulename, "could not write to custom output routine\n");
 		return res;
 	}
 	else
@@ -1411,56 +1437,17 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
 		{
 			res = fwrite(ptr, size, nmemb, AH->OF);
 			if (res != nmemb)
-				die_horribly(AH, modulename, "could not write to output file: %s\n",
+				exit_horribly(modulename, "could not write to output file: %s\n",
 							 strerror(errno));
 			return res;
 		}
 	}
 }
 
-
-/* Report a fatal error and exit(1) */
-static void
-vdie_horribly(ArchiveHandle *AH, const char *modulename,
-			  const char *fmt, va_list ap)
-{
-	vwrite_msg(modulename, fmt, ap);
-
-	if (AH)
-	{
-		if (AH->public.verbose)
-			write_msg(NULL, "*** aborted because of error\n");
-		DisconnectDatabase(&AH->public);
-	}
-
-	exit_nicely(1);
-}
-
-/* As above, but with variable arg list */
-void
-die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
-{
-	va_list		ap;
-
-	va_start(ap, fmt);
-	vdie_horribly(AH, modulename, fmt, ap);
-	va_end(ap);
-}
-
-/* As above, but with a complaint about a particular query. */
-void
-die_on_query_failure(ArchiveHandle *AH, const char *modulename,
-					 const char *query)
-{
-	write_msg(modulename, "query failed: %s",
-			  PQerrorMessage(AH->connection));
-	die_horribly(AH, modulename, "query was: %s\n", query);
-}
-
 /* on some error, we may decide to go on... */
 void
-warn_or_die_horribly(ArchiveHandle *AH,
-					 const char *modulename, const char *fmt,...)
+warn_or_exit_horribly(ArchiveHandle *AH,
+ 					  const char *modulename, const char *fmt,...)
 {
 	va_list		ap;
 
@@ -1497,14 +1484,13 @@ warn_or_die_horribly(ArchiveHandle *AH,
 	AH->lastErrorTE = AH->currentTE;
 
 	va_start(ap, fmt);
+	vwrite_msg(modulename, fmt, ap);
+	va_end(ap);
+
 	if (AH->public.exit_on_error)
-		vdie_horribly(AH, modulename, fmt, ap);
+		exit_nicely(1);
 	else
-	{
-		vwrite_msg(modulename, fmt, ap);
 		AH->public.n_errors++;
-	}
-	va_end(ap);
 }
 
 #ifdef NOT_USED
@@ -1623,7 +1609,7 @@ ReadOffset(ArchiveHandle *AH, pgoff_t * o)
 			break;
 
 		default:
-			die_horribly(AH, modulename, "unexpected data offset flag %d\n", offsetFlg);
+			exit_horribly(modulename, "unexpected data offset flag %d\n", offsetFlg);
 	}
 
 	/*
@@ -1636,7 +1622,7 @@ ReadOffset(ArchiveHandle *AH, pgoff_t * o)
 		else
 		{
 			if ((*AH->ReadBytePtr) (AH) != 0)
-				die_horribly(AH, modulename, "file offset in dump file is too large\n");
+				exit_horribly(modulename, "file offset in dump file is too large\n");
 		}
 	}
 
@@ -1730,7 +1716,7 @@ ReadStr(ArchiveHandle *AH)
 	{
 		buf = (char *) pg_malloc(l + 1);
 		if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
-			die_horribly(AH, modulename, "unexpected end of file\n");
+			exit_horribly(modulename, "unexpected end of file\n");
 
 		buf[l] = '\0';
 	}
@@ -1773,8 +1759,8 @@ _discoverArchiveFormat(ArchiveHandle *AH)
 			char		buf[MAXPGPATH];
 
 			if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH)
-				die_horribly(AH, modulename, "directory name too long: \"%s\"\n",
-							 AH->fSpec);
+				exit_horribly(modulename, "directory name too long: \"%s\"\n",
+							  AH->fSpec);
 			if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
 			{
 				AH->format = archDirectory;
@@ -1783,32 +1769,32 @@ _discoverArchiveFormat(ArchiveHandle *AH)
 
 #ifdef HAVE_LIBZ
 			if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH)
-				die_horribly(AH, modulename, "directory name too long: \"%s\"\n",
-							 AH->fSpec);
+				exit_horribly(modulename, "directory name too long: \"%s\"\n",
+							  AH->fSpec);
 			if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
 			{
 				AH->format = archDirectory;
 				return AH->format;
 			}
 #endif
-			die_horribly(AH, modulename, "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)\n",
-						 AH->fSpec);
+			exit_horribly(modulename, "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)\n",
+						  AH->fSpec);
 			fh = NULL;			/* keep compiler quiet */
 		}
 		else
 		{
 			fh = fopen(AH->fSpec, PG_BINARY_R);
 			if (!fh)
-				die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
-							 AH->fSpec, strerror(errno));
+				exit_horribly(modulename, "could not open input file \"%s\": %s\n",
+							  AH->fSpec, strerror(errno));
 		}
 	}
 	else
 	{
 		fh = stdin;
 		if (!fh)
-			die_horribly(AH, modulename, "could not open input file: %s\n",
-						 strerror(errno));
+			exit_horribly(modulename, "could not open input file: %s\n",
+						  strerror(errno));
 	}
 
 	cnt = fread(sig, 1, 5, fh);
@@ -1816,10 +1802,10 @@ _discoverArchiveFormat(ArchiveHandle *AH)
 	if (cnt != 5)
 	{
 		if (ferror(fh))
-			die_horribly(AH, modulename, "could not read input file: %s\n", strerror(errno));
+			exit_horribly(modulename, "could not read input file: %s\n", strerror(errno));
 		else
-			die_horribly(AH, modulename, "input file is too short (read %lu, expected 5)\n",
-						 (unsigned long) cnt);
+			exit_horribly(modulename, "input file is too short (read %lu, expected 5)\n",
+						  (unsigned long) cnt);
 	}
 
 	/* Save it, just in case we need it later */
@@ -1880,14 +1866,14 @@ _discoverArchiveFormat(ArchiveHandle *AH)
 			 strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
 		{
 			/* looks like it's probably a text format dump. so suggest they try psql */
-			die_horribly(AH, modulename, "input file appears to be a text format dump. Please use psql.\n");
+			exit_horribly(modulename, "input file appears to be a text format dump. Please use psql.\n");
 		}
 
 		if (AH->lookaheadLen != 512)
-			die_horribly(AH, modulename, "input file does not appear to be a valid archive (too short?)\n");
+			exit_horribly(modulename, "input file does not appear to be a valid archive (too short?)\n");
 
 		if (!isValidTarHeader(AH->lookahead))
-			die_horribly(AH, modulename, "input file does not appear to be a valid archive\n");
+			exit_horribly(modulename, "input file does not appear to be a valid archive\n");
 
 		AH->format = archTar;
 	}
@@ -1907,8 +1893,8 @@ _discoverArchiveFormat(ArchiveHandle *AH)
 	/* Close the file */
 	if (wantClose)
 		if (fclose(fh) != 0)
-			die_horribly(AH, modulename, "could not close input file: %s\n",
-						 strerror(errno));
+			exit_horribly(modulename, "could not close input file: %s\n",
+						  strerror(errno));
 
 	return AH->format;
 }
@@ -2027,7 +2013,7 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
 			break;
 
 		default:
-			die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
+			exit_horribly(modulename, "unrecognized file format \"%d\"\n", fmt);
 	}
 
 	return AH;
@@ -2149,9 +2135,9 @@ ReadToc(ArchiveHandle *AH)
 
 		/* Sanity check */
 		if (te->dumpId <= 0)
-			die_horribly(AH, modulename,
-					   "entry ID %d out of range -- perhaps a corrupt TOC\n",
-						 te->dumpId);
+			exit_horribly(modulename,
+						  "entry ID %d out of range -- perhaps a corrupt TOC\n",
+						  te->dumpId);
 
 		te->hadDumper = ReadInt(AH);
 
@@ -2306,13 +2292,13 @@ processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
 		*ptr2 = '\0';
 		encoding = pg_char_to_encoding(ptr1);
 		if (encoding < 0)
-			die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
-						 ptr1);
+			exit_horribly(modulename, "unrecognized encoding \"%s\"\n",
+						  ptr1);
 		AH->public.encoding = encoding;
 	}
 	else
-		die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
-					 te->defn);
+		exit_horribly(modulename, "invalid ENCODING item: %s\n",
+					  te->defn);
 
 	free(defn);
 }
@@ -2329,8 +2315,8 @@ processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
 	else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
 		AH->public.std_strings = false;
 	else
-		die_horribly(AH, modulename, "invalid STDSTRINGS item: %s\n",
-					 te->defn);
+		exit_horribly(modulename, "invalid STDSTRINGS item: %s\n",
+					  te->defn);
 }
 
 static teReqs
@@ -2537,9 +2523,9 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user)
 		res = PQexec(AH->connection, cmd->data);
 
 		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-			/* NOT warn_or_die_horribly... use -O instead to skip this. */
-			die_horribly(AH, modulename, "could not set session user to \"%s\": %s",
-						 user, PQerrorMessage(AH->connection));
+			/* NOT warn_or_exit_horribly... use -O instead to skip this. */
+			exit_horribly(modulename, "could not set session user to \"%s\": %s",
+						  user, PQerrorMessage(AH->connection));
 
 		PQclear(res);
 	}
@@ -2569,9 +2555,9 @@ _doSetWithOids(ArchiveHandle *AH, const bool withOids)
 		res = PQexec(AH->connection, cmd->data);
 
 		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-			warn_or_die_horribly(AH, modulename,
-								 "could not set default_with_oids: %s",
-								 PQerrorMessage(AH->connection));
+			warn_or_exit_horribly(AH, modulename,
+								  "could not set default_with_oids: %s",
+								  PQerrorMessage(AH->connection));
 
 		PQclear(res);
 	}
@@ -2707,9 +2693,9 @@ _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
 		res = PQexec(AH->connection, qry->data);
 
 		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-			warn_or_die_horribly(AH, modulename,
-								 "could not set search_path to \"%s\": %s",
-								 schemaName, PQerrorMessage(AH->connection));
+			warn_or_exit_horribly(AH, modulename,
+								  "could not set search_path to \"%s\": %s",
+								  schemaName, PQerrorMessage(AH->connection));
 
 		PQclear(res);
 	}
@@ -2768,9 +2754,9 @@ _selectTablespace(ArchiveHandle *AH, const char *tablespace)
 		res = PQexec(AH->connection, qry->data);
 
 		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-			warn_or_die_horribly(AH, modulename,
-								 "could not set default_tablespace to %s: %s",
-								 fmtId(want), PQerrorMessage(AH->connection));
+			warn_or_exit_horribly(AH, modulename,
+								  "could not set default_tablespace to %s: %s",
+								  fmtId(want), PQerrorMessage(AH->connection));
 
 		PQclear(res);
 	}
@@ -3150,10 +3136,10 @@ ReadHead(ArchiveHandle *AH)
 	if (!AH->readHeader)
 	{
 		if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5)
-			die_horribly(AH, modulename, "unexpected end of file\n");
+			exit_horribly(modulename, "unexpected end of file\n");
 
 		if (strncmp(tmpMag, "PGDMP", 5) != 0)
-			die_horribly(AH, modulename, "did not find magic string in file header\n");
+			exit_horribly(modulename, "did not find magic string in file header\n");
 
 		AH->vmaj = (*AH->ReadBytePtr) (AH);
 		AH->vmin = (*AH->ReadBytePtr) (AH);
@@ -3166,13 +3152,13 @@ ReadHead(ArchiveHandle *AH)
 		AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
 
 		if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
-			die_horribly(AH, modulename, "unsupported version (%d.%d) in file header\n",
-						 AH->vmaj, AH->vmin);
+			exit_horribly(modulename, "unsupported version (%d.%d) in file header\n",
+						  AH->vmaj, AH->vmin);
 
 		AH->intSize = (*AH->ReadBytePtr) (AH);
 		if (AH->intSize > 32)
-			die_horribly(AH, modulename, "sanity check on integer size (%lu) failed\n",
-						 (unsigned long) AH->intSize);
+			exit_horribly(modulename, "sanity check on integer size (%lu) failed\n",
+						  (unsigned long) AH->intSize);
 
 		if (AH->intSize > sizeof(int))
 			write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
@@ -3185,8 +3171,8 @@ ReadHead(ArchiveHandle *AH)
 		fmt = (*AH->ReadBytePtr) (AH);
 
 		if (AH->format != fmt)
-			die_horribly(AH, modulename, "expected format (%d) differs from format found in file (%d)\n",
-						 AH->format, fmt);
+			exit_horribly(modulename, "expected format (%d) differs from format found in file (%d)\n",
+						  AH->format, fmt);
 	}
 
 	if (AH->version >= K_VERS_1_2)
@@ -3290,6 +3276,66 @@ dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
 		ahprintf(AH, "-- %s %s\n\n", msg, buf);
 }
 
+static void
+setProcessIdentifier(ParallelStateEntry *pse, ArchiveHandle *AH)
+{
+#ifdef WIN32
+	pse->threadId = GetCurrentThreadId();
+#else
+	pse->pid = getpid();
+#endif
+	pse->AH = AH;
+}
+
+static void
+unsetProcessIdentifier(ParallelStateEntry *pse)
+{
+#ifdef WIN32
+	pse->threadId = 0;
+#else
+	pse->pid = 0;
+#endif
+	pse->AH = NULL;
+}
+
+static ParallelStateEntry *
+GetMyPSEntry(ParallelState *pstate)
+{
+	int i;
+
+	for (i = 0; i < pstate->numWorkers; i++)
+#ifdef WIN32
+		if (pstate->pse[i].threadId == GetCurrentThreadId())
+#else
+		if (pstate->pse[i].pid == getpid())
+#endif
+			return &(pstate->pse[i]);
+
+	return NULL;
+}
+
+static void
+archive_close_connection(int code, void *arg)
+{
+	ShutdownInformation *si = (ShutdownInformation *) arg;
+
+	if (si->pstate)
+	{
+		ParallelStateEntry *entry = GetMyPSEntry(si->pstate);
+
+		if (entry != NULL && entry->AH)
+			DisconnectDatabase(&(entry->AH->public));
+	}
+	else if (si->AHX)
+		DisconnectDatabase(si->AHX);
+}
+
+void
+on_exit_close_archive(Archive *AHX)
+{
+	shutdown_info.AHX = AHX;
+	on_exit_nicely(archive_close_connection, &shutdown_info);
+}
 
 /*
  * Main engine for parallel restore.
@@ -3316,10 +3362,17 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
 	TocEntry   *next_work_item;
 	thandle		ret_child;
 	TocEntry   *te;
+	ParallelState *pstate;
+	int			i;
 
 	ahlog(AH, 2, "entering restore_toc_entries_parallel\n");
 
-	slots = (ParallelSlot *) pg_calloc(sizeof(ParallelSlot), n_slots);
+	slots = (ParallelSlot *) pg_calloc(n_slots, sizeof(ParallelSlot));
+	pstate = (ParallelState *) pg_malloc(sizeof(ParallelState));
+	pstate->pse = (ParallelStateEntry *) pg_calloc(n_slots, sizeof(ParallelStateEntry));
+	pstate->numWorkers = ropt->number_of_jobs;
+	for (i = 0; i < pstate->numWorkers; i++)
+		unsetProcessIdentifier(&(pstate->pse[i]));
 
 	/* Adjust dependency information */
 	fix_dependencies(AH);
@@ -3375,6 +3428,12 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
 	 */
 	DisconnectDatabase(&AH->public);
 
+	/*
+	 * Set the pstate in the shutdown_info. The exit handler uses pstate if set
+	 * and falls back to AHX otherwise.
+	 */
+	shutdown_info.pstate = pstate;
+
 	/* blow away any transient state from the old connection */
 	if (AH->currUser)
 		free(AH->currUser);
@@ -3473,6 +3532,7 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
 				args = pg_malloc(sizeof(RestoreArgs));
 				args->AH = CloneArchive(AH);
 				args->te = next_work_item;
+				args->pse = &pstate->pse[next_slot];
 
 				/* run the step in a worker child */
 				child = spawn_restore(args);
@@ -3500,13 +3560,19 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
 		}
 		else
 		{
-			die_horribly(AH, modulename, "worker process crashed: status %d\n",
-						 work_status);
+			exit_horribly(modulename, "worker process crashed: status %d\n",
+						  work_status);
 		}
 	}
 
 	ahlog(AH, 1, "finished main parallel loop\n");
 
+	/*
+	 * Remove the pstate again, so the exit handler will now fall back to
+	 * closing AH->connection again.
+	 */
+	shutdown_info.pstate = NULL;
+
 	/*
 	 * Now reconnect the single parent connection.
 	 */
@@ -3548,23 +3614,23 @@ spawn_restore(RestoreArgs *args)
 	{
 		/* in child process */
 		parallel_restore(args);
-		die_horribly(args->AH, modulename,
-					 "parallel_restore should not return\n");
+		exit_horribly(modulename,
+					  "parallel_restore should not return\n");
 	}
 	else if (child < 0)
 	{
 		/* fork failed */
-		die_horribly(args->AH, modulename,
-					 "could not create worker process: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename,
+					  "could not create worker process: %s\n",
+					  strerror(errno));
 	}
 #else
 	child = (HANDLE) _beginthreadex(NULL, 0, (void *) parallel_restore,
 									args, 0, NULL);
 	if (child == 0)
-		die_horribly(args->AH, modulename,
-					 "could not create worker thread: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename,
+					  "could not create worker thread: %s\n",
+					  strerror(errno));
 #endif
 
 	return child;
@@ -3806,6 +3872,8 @@ parallel_restore(RestoreArgs *args)
 	RestoreOptions *ropt = AH->ropt;
 	int			retval;
 
+	setProcessIdentifier(args->pse, AH);
+
 	/*
 	 * Close and reopen the input file so we have a private file pointer that
 	 * doesn't stomp on anyone else's file pointer, if we're actually going to
@@ -3836,6 +3904,7 @@ parallel_restore(RestoreArgs *args)
 
 	/* And clean up */
 	DisconnectDatabase((Archive *) AH);
+	unsetProcessIdentifier(args->pse);
 
 	/* If we reopened the file, we are done with it, so close it now */
 	if (te->section == SECTION_DATA)
@@ -3881,7 +3950,7 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
 	}
 
 	if (te == NULL)
-		die_horribly(AH, modulename, "could not find slot of finished worker\n");
+		exit_horribly(modulename, "could not find slot of finished worker\n");
 
 	ahlog(AH, 1, "finished item %d %s %s\n",
 		  te->dumpId, te->desc, te->tag);
@@ -3896,8 +3965,8 @@ mark_work_done(ArchiveHandle *AH, TocEntry *ready_list,
 	else if (status == WORKER_IGNORED_ERRORS)
 		AH->public.n_errors++;
 	else if (status != 0)
-		die_horribly(AH, modulename, "worker process failed: exit code %d\n",
-					 status);
+		exit_horribly(modulename, "worker process failed: exit code %d\n",
+					  status);
 
 	reduce_dependencies(AH, te, ready_list);
 }
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 3e304081f215b42f5561659113dfa7966a38643c..c84ec61c11e69751cc9c0d44f983fc6e587b8c8b 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -323,10 +323,9 @@ typedef struct _tocEntry
 	int			nLockDeps;		/* number of such dependencies */
 } TocEntry;
 
+extern void on_exit_close_archive(Archive *AHX);
 
-extern void die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4), noreturn));
-extern void die_on_query_failure(ArchiveHandle *AH, const char *modulename, const char *query) __attribute__((noreturn));
-extern void warn_or_die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
+extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
 
 extern void WriteTOC(ArchiveHandle *AH);
 extern void ReadTOC(ArchiveHandle *AH);
diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
index 31fa3733f06a1ebe44ba783060eaaa0000133560..87242c5560bc3c85864cfbaa168d62b96857759e 100644
--- a/src/bin/pg_dump/pg_backup_custom.c
+++ b/src/bin/pg_dump/pg_backup_custom.c
@@ -146,15 +146,15 @@ InitArchiveFmt_Custom(ArchiveHandle *AH)
 		{
 			AH->FH = fopen(AH->fSpec, PG_BINARY_W);
 			if (!AH->FH)
-				die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
-							 AH->fSpec, strerror(errno));
+				exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+							  AH->fSpec, strerror(errno));
 		}
 		else
 		{
 			AH->FH = stdout;
 			if (!AH->FH)
-				die_horribly(AH, modulename, "could not open output file: %s\n",
-							 strerror(errno));
+				exit_horribly(modulename, "could not open output file: %s\n",
+							  strerror(errno));
 		}
 
 		ctx->hasSeek = checkSeek(AH->FH);
@@ -165,15 +165,15 @@ InitArchiveFmt_Custom(ArchiveHandle *AH)
 		{
 			AH->FH = fopen(AH->fSpec, PG_BINARY_R);
 			if (!AH->FH)
-				die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
-							 AH->fSpec, strerror(errno));
+				exit_horribly(modulename, "could not open input file \"%s\": %s\n",
+							  AH->fSpec, strerror(errno));
 		}
 		else
 		{
 			AH->FH = stdin;
 			if (!AH->FH)
-				die_horribly(AH, modulename, "could not open input file: %s\n",
-							 strerror(errno));
+				exit_horribly(modulename, "could not open input file: %s\n",
+							  strerror(errno));
 		}
 
 		ctx->hasSeek = checkSeek(AH->FH);
@@ -367,7 +367,7 @@ _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
 	lclContext *ctx = (lclContext *) AH->formatData;
 
 	if (oid == 0)
-		die_horribly(AH, modulename, "invalid OID for large object\n");
+		exit_horribly(modulename, "invalid OID for large object\n");
 
 	WriteInt(AH, oid);
 
@@ -437,9 +437,9 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 					break;
 
 				default:		/* Always have a default */
-					die_horribly(AH, modulename,
-								 "unrecognized data block type (%d) while searching archive\n",
-								 blkType);
+					exit_horribly(modulename,
+								  "unrecognized data block type (%d) while searching archive\n",
+								  blkType);
 					break;
 			}
 			_readBlockHeader(AH, &blkType, &id);
@@ -449,8 +449,8 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 	{
 		/* We can just seek to the place we need to be. */
 		if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
-			die_horribly(AH, modulename, "error during file seek: %s\n",
-						 strerror(errno));
+			exit_horribly(modulename, "error during file seek: %s\n",
+						  strerror(errno));
 
 		_readBlockHeader(AH, &blkType, &id);
 	}
@@ -459,25 +459,25 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 	if (blkType == EOF)
 	{
 		if (tctx->dataState == K_OFFSET_POS_NOT_SET)
-			die_horribly(AH, modulename, "could not find block ID %d in archive -- "
-						 "possibly due to out-of-order restore request, "
-						 "which cannot be handled due to lack of data offsets in archive\n",
-						 te->dumpId);
+			exit_horribly(modulename, "could not find block ID %d in archive -- "
+						  "possibly due to out-of-order restore request, "
+						  "which cannot be handled due to lack of data offsets in archive\n",
+						  te->dumpId);
 		else if (!ctx->hasSeek)
-			die_horribly(AH, modulename, "could not find block ID %d in archive -- "
-						 "possibly due to out-of-order restore request, "
-				  "which cannot be handled due to non-seekable input file\n",
-						 te->dumpId);
+			exit_horribly(modulename, "could not find block ID %d in archive -- "
+						  "possibly due to out-of-order restore request, "
+						  "which cannot be handled due to non-seekable input file\n",
+						  te->dumpId);
 		else	/* huh, the dataPos led us to EOF? */
-			die_horribly(AH, modulename, "could not find block ID %d in archive -- "
-						 "possibly corrupt archive\n",
-						 te->dumpId);
+			exit_horribly(modulename, "could not find block ID %d in archive -- "
+						  "possibly corrupt archive\n",
+						  te->dumpId);
 	}
 
 	/* Are we sane? */
 	if (id != te->dumpId)
-		die_horribly(AH, modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
-					 id, te->dumpId);
+		exit_horribly(modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
+					  id, te->dumpId);
 
 	switch (blkType)
 	{
@@ -490,8 +490,8 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 			break;
 
 		default:				/* Always have a default */
-			die_horribly(AH, modulename, "unrecognized data block type %d while restoring archive\n",
-						 blkType);
+			exit_horribly(modulename, "unrecognized data block type %d while restoring archive\n",
+						  blkType);
 			break;
 	}
 }
@@ -571,11 +571,11 @@ _skipData(ArchiveHandle *AH)
 		if (cnt != blkLen)
 		{
 			if (feof(AH->FH))
-				die_horribly(AH, modulename,
-							 "could not read from input file: end of file\n");
+				exit_horribly(modulename,
+							  "could not read from input file: end of file\n");
 			else
-				die_horribly(AH, modulename,
-					"could not read from input file: %s\n", strerror(errno));
+				exit_horribly(modulename,
+							  "could not read from input file: %s\n", strerror(errno));
 		}
 
 		ctx->filePos += blkLen;
@@ -604,7 +604,7 @@ _WriteByte(ArchiveHandle *AH, const int i)
 	if (res != EOF)
 		ctx->filePos += 1;
 	else
-		die_horribly(AH, modulename, "could not write byte: %s\n", strerror(errno));
+		exit_horribly(modulename, "could not write byte: %s\n", strerror(errno));
 	return res;
 }
 
@@ -624,7 +624,7 @@ _ReadByte(ArchiveHandle *AH)
 
 	res = getc(AH->FH);
 	if (res == EOF)
-		die_horribly(AH, modulename, "unexpected end of file\n");
+		exit_horribly(modulename, "unexpected end of file\n");
 	ctx->filePos += 1;
 	return res;
 }
@@ -645,7 +645,7 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
 	res = fwrite(buf, 1, len, AH->FH);
 
 	if (res != len)
-		die_horribly(AH, modulename,
+		exit_horribly(modulename,
 					 "could not write to output file: %s\n", strerror(errno));
 
 	ctx->filePos += res;
@@ -712,7 +712,7 @@ _CloseArchive(ArchiveHandle *AH)
 	}
 
 	if (fclose(AH->FH) != 0)
-		die_horribly(AH, modulename, "could not close archive file: %s\n", strerror(errno));
+		exit_horribly(modulename, "could not close archive file: %s\n", strerror(errno));
 
 	AH->FH = NULL;
 }
@@ -731,37 +731,37 @@ _ReopenArchive(ArchiveHandle *AH)
 	pgoff_t		tpos;
 
 	if (AH->mode == archModeWrite)
-		die_horribly(AH, modulename, "can only reopen input archives\n");
+		exit_horribly(modulename, "can only reopen input archives\n");
 
 	/*
 	 * These two cases are user-facing errors since they represent unsupported
 	 * (but not invalid) use-cases.  Word the error messages appropriately.
 	 */
 	if (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0)
-		die_horribly(AH, modulename, "parallel restore from stdin is not supported\n");
+		exit_horribly(modulename, "parallel restore from stdin is not supported\n");
 	if (!ctx->hasSeek)
-		die_horribly(AH, modulename, "parallel restore from non-seekable file is not supported\n");
+		exit_horribly(modulename, "parallel restore from non-seekable file is not supported\n");
 
 	errno = 0;
 	tpos = ftello(AH->FH);
 	if (errno)
-		die_horribly(AH, modulename, "could not determine seek position in archive file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
+					  strerror(errno));
 
 #ifndef WIN32
 	if (fclose(AH->FH) != 0)
-		die_horribly(AH, modulename, "could not close archive file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename, "could not close archive file: %s\n",
+					  strerror(errno));
 #endif
 
 	AH->FH = fopen(AH->fSpec, PG_BINARY_R);
 	if (!AH->FH)
-		die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
-					 AH->fSpec, strerror(errno));
+		exit_horribly(modulename, "could not open input file \"%s\": %s\n",
+					  AH->fSpec, strerror(errno));
 
 	if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
-		die_horribly(AH, modulename, "could not set seek position in archive file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename, "could not set seek position in archive file: %s\n",
+					  strerror(errno));
 }
 
 /*
@@ -778,7 +778,7 @@ _Clone(ArchiveHandle *AH)
 
 	/* sanity check, shouldn't happen */
 	if (ctx->cs != NULL)
-		die_horribly(AH, modulename, "compressor active\n");
+		exit_horribly(modulename, "compressor active\n");
 
 	/*
 	 * Note: we do not make a local lo_buf because we expect at most one BLOBS
@@ -840,7 +840,7 @@ _readBlockHeader(ArchiveHandle *AH, int *type, int *id)
 	int			byt;
 
 	/*
-	 * Note: if we are at EOF with a pre-1.3 input file, we'll die_horribly
+	 * Note: if we are at EOF with a pre-1.3 input file, we'll exit_horribly
 	 * inside ReadInt rather than returning EOF.  It doesn't seem worth
 	 * jumping through hoops to deal with that case better, because no such
 	 * files are likely to exist in the wild: only some 7.1 development
@@ -905,10 +905,10 @@ _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)
 	if (cnt != blkLen)
 	{
 		if (feof(AH->FH))
-			die_horribly(AH, modulename,
-						 "could not read from input file: end of file\n");
+			exit_horribly(modulename,
+						  "could not read from input file: end of file\n");
 		else
-			die_horribly(AH, modulename,
+			exit_horribly(modulename,
 					"could not read from input file: %s\n", strerror(errno));
 	}
 	return cnt;
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index a843eacc0c842bdda2c2bdce853f9e37e3283ce6..b315e681926dc343481e49822d9cb2b71dcb788f 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -30,13 +30,13 @@ static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, const char *
 static void notice_processor(void *arg, const char *message);
 
 static int
-_parse_version(ArchiveHandle *AH, const char *versionString)
+_parse_version(const char *versionString)
 {
 	int			v;
 
 	v = parse_version(versionString);
 	if (v < 0)
-		die_horribly(AH, modulename, "could not parse version string \"%s\"\n", versionString);
+		exit_horribly(modulename, "could not parse version string \"%s\"\n", versionString);
 
 	return v;
 }
@@ -48,13 +48,13 @@ _check_database_version(ArchiveHandle *AH)
 	const char *remoteversion_str;
 	int			remoteversion;
 
-	myversion = _parse_version(AH, PG_VERSION);
+	myversion = _parse_version(PG_VERSION);
 
 	remoteversion_str = PQparameterStatus(AH->connection, "server_version");
 	if (!remoteversion_str)
-		die_horribly(AH, modulename, "could not get server_version from libpq\n");
+		exit_horribly(modulename, "could not get server_version from libpq\n");
 
-	remoteversion = _parse_version(AH, remoteversion_str);
+	remoteversion = _parse_version(remoteversion_str);
 
 	AH->public.remoteVersionStr = pg_strdup(remoteversion_str);
 	AH->public.remoteVersion = remoteversion;
@@ -67,7 +67,7 @@ _check_database_version(ArchiveHandle *AH)
 	{
 		write_msg(NULL, "server version: %s; %s version: %s\n",
 				  remoteversion_str, progname, PG_VERSION);
-		die_horribly(AH, NULL, "aborting because of server version mismatch\n");
+		exit_horribly(NULL, "aborting because of server version mismatch\n");
 	}
 }
 
@@ -145,7 +145,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
 	{
 		password = simple_prompt("Password: ", 100, false);
 		if (password == NULL)
-			die_horribly(AH, modulename, "out of memory\n");
+			exit_horribly(modulename, "out of memory\n");
 	}
 
 	do
@@ -176,12 +176,12 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
 		free(values);
 
 		if (!newConn)
-			die_horribly(AH, modulename, "failed to reconnect to database\n");
+			exit_horribly(modulename, "failed to reconnect to database\n");
 
 		if (PQstatus(newConn) == CONNECTION_BAD)
 		{
 			if (!PQconnectionNeedsPassword(newConn))
-				die_horribly(AH, modulename, "could not reconnect to database: %s",
+				exit_horribly(modulename, "could not reconnect to database: %s",
 							 PQerrorMessage(newConn));
 			PQfinish(newConn);
 
@@ -197,10 +197,10 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
 			if (AH->promptPassword != TRI_NO)
 				password = simple_prompt("Password: ", 100, false);
 			else
-				die_horribly(AH, modulename, "connection needs password\n");
+				exit_horribly(modulename, "connection needs password\n");
 
 			if (password == NULL)
-				die_horribly(AH, modulename, "out of memory\n");
+				exit_horribly(modulename, "out of memory\n");
 			new_pass = true;
 		}
 	} while (new_pass);
@@ -238,13 +238,13 @@ ConnectDatabase(Archive *AHX,
 	bool		new_pass;
 
 	if (AH->connection)
-		die_horribly(AH, modulename, "already connected to a database\n");
+		exit_horribly(modulename, "already connected to a database\n");
 
 	if (prompt_password == TRI_YES && password == NULL)
 	{
 		password = simple_prompt("Password: ", 100, false);
 		if (password == NULL)
-			die_horribly(AH, modulename, "out of memory\n");
+			exit_horribly(modulename, "out of memory\n");
 	}
 	AH->promptPassword = prompt_password;
 
@@ -280,7 +280,7 @@ ConnectDatabase(Archive *AHX,
 		free(values);
 
 		if (!AH->connection)
-			die_horribly(AH, modulename, "failed to connect to database\n");
+			exit_horribly(modulename, "failed to connect to database\n");
 
 		if (PQstatus(AH->connection) == CONNECTION_BAD &&
 			PQconnectionNeedsPassword(AH->connection) &&
@@ -290,7 +290,7 @@ ConnectDatabase(Archive *AHX,
 			PQfinish(AH->connection);
 			password = simple_prompt("Password: ", 100, false);
 			if (password == NULL)
-				die_horribly(AH, modulename, "out of memory\n");
+				exit_horribly(modulename, "out of memory\n");
 			new_pass = true;
 		}
 	} while (new_pass);
@@ -299,7 +299,7 @@ ConnectDatabase(Archive *AHX,
 
 	/* check to see that the backend connection was successfully made */
 	if (PQstatus(AH->connection) == CONNECTION_BAD)
-		die_horribly(AH, modulename, "connection to database \"%s\" failed: %s",
+		exit_horribly(modulename, "connection to database \"%s\" failed: %s",
 					 PQdb(AH->connection), PQerrorMessage(AH->connection));
 
 	/* check for version mismatch */
@@ -331,6 +331,14 @@ notice_processor(void *arg, const char *message)
 	write_msg(NULL, "%s", message);
 }
 
+/* Like exit_horribly(), but with a complaint about a particular query. */
+static void
+die_on_query_failure(ArchiveHandle *AH, const char *modulename, const char *query)
+{
+	write_msg(modulename, "query failed: %s",
+			  PQerrorMessage(AH->connection));
+	exit_horribly(modulename, "query was: %s\n", query);
+}
 
 void
 ExecuteSqlStatement(Archive *AHX, const char *query)
@@ -393,8 +401,8 @@ ExecuteSqlCommand(ArchiveHandle *AH, const char *qry, const char *desc)
 				errStmt[DB_MAX_ERR_STMT - 2] = '.';
 				errStmt[DB_MAX_ERR_STMT - 1] = '\0';
 			}
-			warn_or_die_horribly(AH, modulename, "%s: %s    Command was: %s\n",
-								 desc, PQerrorMessage(conn), errStmt);
+			warn_or_exit_horribly(AH, modulename, "%s: %s    Command was: %s\n",
+								  desc, PQerrorMessage(conn), errStmt);
 			break;
 	}
 
@@ -495,8 +503,8 @@ ExecuteSqlCommandBuf(ArchiveHandle *AH, const char *buf, size_t bufLen)
 		 */
 		if (AH->pgCopyIn &&
 			PQputCopyData(AH->connection, buf, bufLen) <= 0)
-			die_horribly(AH, modulename, "error returned by PQputCopyData: %s",
-						 PQerrorMessage(AH->connection));
+			exit_horribly(modulename, "error returned by PQputCopyData: %s",
+						  PQerrorMessage(AH->connection));
 	}
 	else if (AH->outputKind == OUTPUT_OTHERDATA)
 	{
@@ -541,14 +549,14 @@ EndDBCopyMode(ArchiveHandle *AH, TocEntry *te)
 		PGresult   *res;
 
 		if (PQputCopyEnd(AH->connection, NULL) <= 0)
-			die_horribly(AH, modulename, "error returned by PQputCopyEnd: %s",
-						 PQerrorMessage(AH->connection));
+			exit_horribly(modulename, "error returned by PQputCopyEnd: %s",
+						  PQerrorMessage(AH->connection));
 
 		/* Check command status and return to normal libpq state */
 		res = PQgetResult(AH->connection);
 		if (PQresultStatus(res) != PGRES_COMMAND_OK)
-			warn_or_die_horribly(AH, modulename, "COPY failed for table \"%s\": %s",
-								 te->tag, PQerrorMessage(AH->connection));
+			warn_or_exit_horribly(AH, modulename, "COPY failed for table \"%s\": %s",
+								  te->tag, PQerrorMessage(AH->connection));
 		PQclear(res);
 
 		AH->pgCopyIn = false;
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index 4b59516fe46d425e5c1fa8158feb8f05e30f73b0..8d43cd2ade46eddada54e6e4e17e560c3057ad4a 100644
--- a/src/bin/pg_dump/pg_backup_directory.c
+++ b/src/bin/pg_dump/pg_backup_directory.c
@@ -142,7 +142,7 @@ InitArchiveFmt_Directory(ArchiveHandle *AH)
 	 */
 
 	if (!AH->fSpec || strcmp(AH->fSpec, "") == 0)
-		die_horribly(AH, modulename, "no output directory specified\n");
+		exit_horribly(modulename, "no output directory specified\n");
 
 	ctx->directory = AH->fSpec;
 
@@ -160,9 +160,9 @@ InitArchiveFmt_Directory(ArchiveHandle *AH)
 
 		tocFH = cfopen_read(fname, PG_BINARY_R);
 		if (tocFH == NULL)
-			die_horribly(AH, modulename,
-						 "could not open input file \"%s\": %s\n",
-						 fname, strerror(errno));
+			exit_horribly(modulename,
+						  "could not open input file \"%s\": %s\n",
+						  fname, strerror(errno));
 
 		ctx->dataFH = tocFH;
 
@@ -177,7 +177,7 @@ InitArchiveFmt_Directory(ArchiveHandle *AH)
 
 		/* Nothing else in the file, so close it again... */
 		if (cfclose(tocFH) != 0)
-			die_horribly(AH, modulename, "could not close TOC file: %s\n",
+			exit_horribly(modulename, "could not close TOC file: %s\n",
 						 strerror(errno));
 		ctx->dataFH = NULL;
 	}
@@ -288,8 +288,8 @@ _StartData(ArchiveHandle *AH, TocEntry *te)
 
 	ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
 	if (ctx->dataFH == NULL)
-		die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
-					 fname, strerror(errno));
+		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+					  fname, strerror(errno));
 }
 
 /*
@@ -346,7 +346,7 @@ _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
 	cfp = cfopen_read(filename, PG_BINARY_R);
 
 	if (!cfp)
-		die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
+		exit_horribly(modulename, "could not open input file \"%s\": %s\n",
 					 filename, strerror(errno));
 
 	buf = pg_malloc(ZLIB_OUT_SIZE);
@@ -357,7 +357,7 @@ _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
 
 	free(buf);
 	if (cfclose(cfp) != 0)
-		die_horribly(AH, modulename, "could not close data file: %s\n",
+		exit_horribly(modulename, "could not close data file: %s\n",
 					 strerror(errno));
 }
 
@@ -397,8 +397,8 @@ _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
 	ctx->blobsTocFH = cfopen_read(fname, PG_BINARY_R);
 
 	if (ctx->blobsTocFH == NULL)
-		die_horribly(AH, modulename, "could not open large object TOC file \"%s\" for input: %s\n",
-					 fname, strerror(errno));
+		exit_horribly(modulename, "could not open large object TOC file \"%s\" for input: %s\n",
+					  fname, strerror(errno));
 
 	/* Read the blobs TOC file line-by-line, and process each blob */
 	while ((cfgets(ctx->blobsTocFH, line, MAXPGPATH)) != NULL)
@@ -407,8 +407,8 @@ _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
 		char		path[MAXPGPATH];
 
 		if (sscanf(line, "%u %s\n", &oid, fname) != 2)
-			die_horribly(AH, modulename, "invalid line in large object TOC file: %s\n",
-						 line);
+			exit_horribly(modulename, "invalid line in large object TOC file: %s\n",
+						  line);
 
 		StartRestoreBlob(AH, oid, ropt->dropSchema);
 		snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, fname);
@@ -416,12 +416,12 @@ _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
 		EndRestoreBlob(AH, oid);
 	}
 	if (!cfeof(ctx->blobsTocFH))
-		die_horribly(AH, modulename, "error reading large object TOC file \"%s\"\n",
+		exit_horribly(modulename, "error reading large object TOC file \"%s\"\n",
 					 fname);
 
 	if (cfclose(ctx->blobsTocFH) != 0)
-		die_horribly(AH, modulename, "could not close large object TOC file \"%s\": %s\n",
-					 fname, strerror(errno));
+		exit_horribly(modulename, "could not close large object TOC file \"%s\": %s\n",
+					  fname, strerror(errno));
 
 	ctx->blobsTocFH = NULL;
 
@@ -441,7 +441,7 @@ _WriteByte(ArchiveHandle *AH, const int i)
 	lclContext *ctx = (lclContext *) AH->formatData;
 
 	if (cfwrite(&c, 1, ctx->dataFH) != 1)
-		die_horribly(AH, modulename, "could not write byte\n");
+		exit_horribly(modulename, "could not write byte\n");
 
 	return 1;
 }
@@ -460,7 +460,7 @@ _ReadByte(ArchiveHandle *AH)
 
 	res = cfgetc(ctx->dataFH);
 	if (res == EOF)
-		die_horribly(AH, modulename, "unexpected end of file\n");
+		exit_horribly(modulename, "unexpected end of file\n");
 
 	return res;
 }
@@ -477,7 +477,7 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
 
 	res = cfwrite(buf, len, ctx->dataFH);
 	if (res != len)
-		die_horribly(AH, modulename, "could not write to output file: %s\n",
+		exit_horribly(modulename, "could not write to output file: %s\n",
 					 strerror(errno));
 
 	return res;
@@ -524,8 +524,8 @@ _CloseArchive(ArchiveHandle *AH)
 		/* The TOC is always created uncompressed */
 		tocFH = cfopen_write(fname, PG_BINARY_W, 0);
 		if (tocFH == NULL)
-			die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
-						 fname, strerror(errno));
+			exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+						  fname, strerror(errno));
 		ctx->dataFH = tocFH;
 
 		/*
@@ -538,8 +538,8 @@ _CloseArchive(ArchiveHandle *AH)
 		AH->format = archDirectory;
 		WriteToc(AH);
 		if (cfclose(tocFH) != 0)
-			die_horribly(AH, modulename, "could not close TOC file: %s\n",
-						 strerror(errno));
+			exit_horribly(modulename, "could not close TOC file: %s\n",
+						  strerror(errno));
 		WriteDataChunks(AH);
 	}
 	AH->FH = NULL;
@@ -568,8 +568,8 @@ _StartBlobs(ArchiveHandle *AH, TocEntry *te)
 	/* The blob TOC file is never compressed */
 	ctx->blobsTocFH = cfopen_write(fname, "ab", 0);
 	if (ctx->blobsTocFH == NULL)
-		die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
-					 fname, strerror(errno));
+		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
+					  fname, strerror(errno));
 }
 
 /*
@@ -588,7 +588,7 @@ _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
 	ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
 
 	if (ctx->dataFH == NULL)
-		die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
+		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
 					 fname, strerror(errno));
 }
 
@@ -611,7 +611,7 @@ _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
 	/* register the blob in blobs.toc */
 	len = snprintf(buf, sizeof(buf), "%u blob_%u.dat\n", oid, oid);
 	if (cfwrite(buf, len, ctx->blobsTocFH) != len)
-		die_horribly(AH, modulename, "could not write to blobs TOC file\n");
+		exit_horribly(modulename, "could not write to blobs TOC file\n");
 }
 
 /*
@@ -667,7 +667,7 @@ prependDirectory(ArchiveHandle *AH, const char *relativeFilename)
 	dname = ctx->directory;
 
 	if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH)
-		die_horribly(AH, modulename, "path name too long: %s", dname);
+		exit_horribly(modulename, "path name too long: %s", dname);
 
 	strcpy(buf, dname);
 	strcat(buf, "/");
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index 201f0d9a212070e7bbf012eeaa7d2ebb0a634873..ba1e461af45576d86427e39cf35f52a42767ceba 100644
--- a/src/bin/pg_dump/pg_backup_null.c
+++ b/src/bin/pg_dump/pg_backup_null.c
@@ -74,7 +74,7 @@ InitArchiveFmt_Null(ArchiveHandle *AH)
 	 * Now prevent reading...
 	 */
 	if (AH->mode == archModeRead)
-		die_horribly(AH, NULL, "this format cannot be read\n");
+		exit_horribly(NULL, "this format cannot be read\n");
 }
 
 /*
@@ -149,7 +149,7 @@ _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
 	bool		old_blob_style = (AH->version < K_VERS_1_12);
 
 	if (oid == 0)
-		die_horribly(AH, NULL, "invalid OID for large object\n");
+		exit_horribly(NULL, "invalid OID for large object\n");
 
 	/* With an old archive we must do drop and create logic here */
 	if (old_blob_style && AH->ropt->dropSchema)
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index 4823edec7fea0a924e42c0b7f82d6efdbba152b6..451c9574f7cbcefd1a84c3d9fde0fe45ee61d3ac 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -355,7 +355,7 @@ tarOpen(ArchiveHandle *AH, const char *filename, char mode)
 				 * Couldn't find the requested file. Future: do SEEK(0) and
 				 * retry.
 				 */
-				die_horribly(AH, modulename, "could not find file \"%s\" in archive\n", filename);
+				exit_horribly(modulename, "could not find file \"%s\" in archive\n", filename);
 			}
 			else
 			{
@@ -369,7 +369,7 @@ tarOpen(ArchiveHandle *AH, const char *filename, char mode)
 		if (AH->compression == 0)
 			tm->nFH = ctx->tarFH;
 		else
-			die_horribly(AH, modulename, "compression is not supported by tar archive format\n");
+			exit_horribly(modulename, "compression is not supported by tar archive format\n");
 		/* tm->zFH = gzdopen(dup(fileno(ctx->tarFH)), "rb"); */
 #else
 		tm->nFH = ctx->tarFH;
@@ -411,7 +411,7 @@ tarOpen(ArchiveHandle *AH, const char *filename, char mode)
 #endif
 
 		if (tm->tmpFH == NULL)
-			die_horribly(AH, modulename, "could not generate temporary file name: %s\n", strerror(errno));
+			exit_horribly(modulename, "could not generate temporary file name: %s\n", strerror(errno));
 
 #ifdef HAVE_LIBZ
 
@@ -420,7 +420,7 @@ tarOpen(ArchiveHandle *AH, const char *filename, char mode)
 			sprintf(fmode, "wb%d", AH->compression);
 			tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode);
 			if (tm->zFH == NULL)
-				die_horribly(AH, modulename, "could not open temporary file\n");
+				exit_horribly(modulename, "could not open temporary file\n");
 		}
 		else
 			tm->nFH = tm->tmpFH;
@@ -447,7 +447,7 @@ tarClose(ArchiveHandle *AH, TAR_MEMBER *th)
 	 */
 	if (AH->compression != 0)
 		if (GZCLOSE(th->zFH) != 0)
-			die_horribly(AH, modulename, "could not close tar member\n");
+			exit_horribly(modulename, "could not close tar member\n");
 
 	if (th->mode == 'w')
 		_tarAddFile(AH, th);	/* This will close the temp file */
@@ -547,7 +547,7 @@ _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh)
 				res = fread(&((char *) buf)[used], 1, len, th->nFH);
 		}
 		else
-			die_horribly(AH, modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
+			exit_horribly(modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
 	}
 
 	ctx->tarFHpos += res + used;
@@ -584,8 +584,8 @@ tarWrite(const void *buf, size_t len, TAR_MEMBER *th)
 		res = fwrite(buf, 1, len, th->nFH);
 
 	if (res != len)
-		die_horribly(th->AH, modulename,
-					 "could not write to output file: %s\n", strerror(errno));
+		exit_horribly(modulename,
+					  "could not write to output file: %s\n", strerror(errno));
 
 	th->pos += res;
 	return res;
@@ -672,8 +672,8 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 		 * we search the string for it in a paranoid sort of way.
 		 */
 		if (strncmp(tmpCopy, "copy ", 5) != 0)
-			die_horribly(AH, modulename,
-						 "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
+			exit_horribly(modulename,
+						  "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
 
 		pos1 = 5;
 		for (pos1 = 5; pos1 < strlen(tmpCopy); pos1++)
@@ -690,9 +690,9 @@ _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 				break;
 
 		if (pos2 >= strlen(tmpCopy))
-			die_horribly(AH, modulename,
-						 "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n",
-						 tmpCopy, (unsigned long) pos1);
+			exit_horribly(modulename,
+						  "invalid COPY statement -- could not find \"from stdin\" in string \"%s\" starting at position %lu\n",
+						  tmpCopy, (unsigned long) pos1);
 
 		ahwrite(tmpCopy, 1, pos2, AH);	/* 'copy "table" [with oids]' */
 		ahprintf(AH, " from '$$PATH$$/%s' %s", tctx->filename, &tmpCopy[pos2 + 10]);
@@ -784,7 +784,7 @@ _ReadByte(ArchiveHandle *AH)
 
 	res = tarRead(&c, 1, ctx->FH);
 	if (res != 1)
-		die_horribly(AH, modulename, "unexpected end of file\n");
+		exit_horribly(modulename, "unexpected end of file\n");
 	ctx->filePos += 1;
 	return c;
 }
@@ -878,7 +878,7 @@ _CloseArchive(ArchiveHandle *AH)
 		for (i = 0; i < 512; i++)
 		{
 			if (fputc(0, ctx->tarFH) == EOF)
-				die_horribly(AH, modulename,
+				exit_horribly(modulename,
 					   "could not write null block at end of tar archive\n");
 		}
 	}
@@ -934,7 +934,7 @@ _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid)
 	char	   *sfx;
 
 	if (oid == 0)
-		die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
+		exit_horribly(modulename, "invalid OID for large object (%u)\n", oid);
 
 	if (AH->compression != 0)
 		sfx = ".gz";
@@ -1077,7 +1077,7 @@ _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)
 	 * because pgoff_t can't exceed the compared maximum on their platform.
 	 */
 	if (th->fileLen > MAX_TAR_MEMBER_FILELEN)
-		die_horribly(AH, modulename, "archive member too large for tar format\n");
+		exit_horribly(modulename, "archive member too large for tar format\n");
 
 	_tarWriteHeader(th);
 
@@ -1085,15 +1085,15 @@ _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)
 	{
 		res = fwrite(buf, 1, cnt, th->tarFH);
 		if (res != cnt)
-			die_horribly(AH, modulename,
-						 "could not write to output file: %s\n",
-						 strerror(errno));
+			exit_horribly(modulename,
+						  "could not write to output file: %s\n",
+						  strerror(errno));
 		len += res;
 	}
 
 	if (fclose(tmp) != 0)		/* This *should* delete it... */
-		die_horribly(AH, modulename, "could not close temporary file: %s\n",
-					 strerror(errno));
+		exit_horribly(modulename, "could not close temporary file: %s\n",
+					  strerror(errno));
 
 	if (len != th->fileLen)
 	{
@@ -1102,15 +1102,15 @@ _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th)
 
 		snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len);
 		snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen);
-		die_horribly(AH, modulename, "actual file length (%s) does not match expected (%s)\n",
-					 buf1, buf2);
+		exit_horribly(modulename, "actual file length (%s) does not match expected (%s)\n",
+					  buf1, buf2);
 	}
 
 	pad = ((len + 511) & ~511) - len;
 	for (i = 0; i < pad; i++)
 	{
 		if (fputc('\0', th->tarFH) == EOF)
-			die_horribly(AH, modulename, "could not output padding at end of tar member\n");
+			exit_horribly(modulename, "could not output padding at end of tar member\n");
 	}
 
 	ctx->tarFHpos += len + pad;
@@ -1159,7 +1159,7 @@ _tarPositionTo(ArchiveHandle *AH, const char *filename)
 	if (!_tarGetHeader(AH, th))
 	{
 		if (filename)
-			die_horribly(AH, modulename, "could not find header for file \"%s\" in tar archive\n", filename);
+			exit_horribly(modulename, "could not find header for file \"%s\" in tar archive\n", filename);
 		else
 		{
 			/*
@@ -1177,9 +1177,9 @@ _tarPositionTo(ArchiveHandle *AH, const char *filename)
 
 		id = atoi(th->targetFile);
 		if ((TocIDRequired(AH, id, AH->ropt) & REQ_DATA) != 0)
-			die_horribly(AH, modulename, "restoring data out of order is not supported in this archive format: "
-						 "\"%s\" is required, but comes before \"%s\" in the archive file.\n",
-						 th->targetFile, filename);
+			exit_horribly(modulename, "restoring data out of order is not supported in this archive format: "
+						  "\"%s\" is required, but comes before \"%s\" in the archive file.\n",
+						  th->targetFile, filename);
 
 		/* Header doesn't match, so read to next header */
 		len = ((th->fileLen + 511) & ~511);		/* Padded length */
@@ -1189,7 +1189,7 @@ _tarPositionTo(ArchiveHandle *AH, const char *filename)
 			_tarReadRaw(AH, &header[0], 512, NULL, ctx->tarFH);
 
 		if (!_tarGetHeader(AH, th))
-			die_horribly(AH, modulename, "could not find header for file \"%s\" in tar archive\n", filename);
+			exit_horribly(modulename, "could not find header for file \"%s\" in tar archive\n", filename);
 	}
 
 	ctx->tarNextMember = ctx->tarFHpos + ((th->fileLen + 511) & ~511);
@@ -1222,7 +1222,7 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
 
 			snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ftello(ctx->tarFH));
 			snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ftello(ctx->tarFHpos));
-			die_horribly(AH, modulename,
+			exit_horribly(modulename,
 			  "mismatch in actual vs. predicted file position (%s vs. %s)\n",
 						 buf1, buf2);
 		}
@@ -1237,11 +1237,11 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
 			return 0;
 
 		if (len != 512)
-			die_horribly(AH, modulename,
-						 ngettext("incomplete tar header found (%lu byte)\n",
-								  "incomplete tar header found (%lu bytes)\n",
-								  len),
-						 (unsigned long) len);
+			exit_horribly(modulename,
+						  ngettext("incomplete tar header found (%lu byte)\n",
+								   "incomplete tar header found (%lu bytes)\n",
+								   len),
+						  (unsigned long) len);
 
 		/* Calc checksum */
 		chk = _tarChecksum(h);
@@ -1285,10 +1285,10 @@ _tarGetHeader(ArchiveHandle *AH, TAR_MEMBER *th)
 		char		buf[100];
 
 		snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ftello(ctx->tarFH));
-		die_horribly(AH, modulename,
-					 "corrupt tar header found in %s "
-					 "(expected %d, computed %d) file position %s\n",
-					 tag, sum, chk, buf);
+		exit_horribly(modulename,
+					  "corrupt tar header found in %s "
+					  "(expected %d, computed %d) file position %s\n",
+					  tag, sum, chk, buf);
 	}
 
 	th->targetFile = pg_strdup(tag);
@@ -1379,5 +1379,5 @@ _tarWriteHeader(TAR_MEMBER *th)
 	}
 
 	if (fwrite(h, 1, 512, th->tarFH) != 512)
-		die_horribly(th->AH, modulename, "could not write to output file: %s\n", strerror(errno));
+		exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno));
 }
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 4545f97a63d804af41cb8a4e20010bc495f28e9f..14389bd0d37293427b67c2b3d6608121991fe89c 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -144,7 +144,6 @@ static int	serializable_deferrable = 0;
 
 
 static void help(const char *progname);
-static void pgdump_cleanup_at_exit(int code, void *arg);
 static void setup_connection(Archive *AH, const char *dumpencoding,
 				 char *use_role);
 static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
@@ -575,7 +574,9 @@ main(int argc, char **argv)
 
 	/* Open the output file */
 	fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode);
-	on_exit_nicely(pgdump_cleanup_at_exit, fout);
+
+	/* Register the cleanup hook */
+	on_exit_close_archive(fout);
 
 	if (fout == NULL)
 		exit_horribly(NULL, "could not open output file \"%s\" for writing\n", filename);
@@ -836,14 +837,6 @@ help(const char *progname)
 	printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
 }
 
-static void
-pgdump_cleanup_at_exit(int code, void *arg)
-{
-	Archive	   *AH = (Archive *) arg;
-
-	DisconnectDatabase(AH);
-}
-
 static void
 setup_connection(Archive *AH, const char *dumpencoding, char *use_role)
 {
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index 1e2b6fd046bdbdcf480f802b32ef2cf7703e305d..bd2feff11456500fe32b606c9bfa88199fe954ed 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -379,6 +379,13 @@ main(int argc, char **argv)
 
 	AH = OpenArchive(inputFileSpec, opts->format);
 
+	/*
+	 * We don't have a connection yet but that doesn't matter. The connection
+	 * is initialized to NULL and if we terminate through exit_nicely() while
+	 * it's still NULL, the cleanup function will just be a no-op.
+	 */
+	on_exit_close_archive(AH);
+
 	/* Let the archiver know how noisy to be */
 	AH->verbose = opts->verbose;