pg_dump_die_horribly.diff

text/x-patch

Filename: pg_dump_die_horribly.diff
Type: text/x-patch
Part: 0
Message: Re: patch for parallel pg_dump

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/bin/pg_dump/compress_io.c 0 0
src/bin/pg_dump/dumputils.c 0 0
src/bin/pg_dump/dumputils.h 0 0
src/bin/pg_dump/pg_backup_archiver.c 0 0
src/bin/pg_dump/pg_backup_archiver.h 0 0
src/bin/pg_dump/pg_backup_custom.c 0 0
src/bin/pg_dump/pg_backup_db.c 0 0
src/bin/pg_dump/pg_backup_directory.c 0 0
src/bin/pg_dump/pg_backup_files.c 0 0
src/bin/pg_dump/pg_backup.h 0 0
src/bin/pg_dump/pg_backup_null.c 0 0
src/bin/pg_dump/pg_backup_tar.c 0 0
src/bin/pg_dump/pg_dump.c 0 0
src/bin/pg_dump/pg_restore.c 0 0
diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c
index c30b8f9..ff8e714 100644
*** a/src/bin/pg_dump/compress_io.c
--- b/src/bin/pg_dump/compress_io.c
*************** EndCompressorZlib(ArchiveHandle *AH, Com
*** 256,263 ****
  	DeflateCompressorZlib(AH, cs, true);
  
  	if (deflateEnd(zp) != Z_OK)
! 		die_horribly(AH, modulename,
! 					 "could not close compression stream: %s\n", zp->msg);
  
  	free(cs->zlibOut);
  	free(cs->zp);
--- 256,263 ----
  	DeflateCompressorZlib(AH, cs, true);
  
  	if (deflateEnd(zp) != Z_OK)
! 		exit_horribly(modulename,
! 					  "could not close compression stream: %s\n", zp->msg);
  
  	free(cs->zlibOut);
  	free(cs->zp);
*************** DeflateCompressorZlib(ArchiveHandle *AH,
*** 274,281 ****
  	{
  		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);
  		if ((flush && (zp->avail_out < cs->zlibOutSize))
  			|| (zp->avail_out == 0)
  			|| (zp->avail_in != 0)
--- 274,281 ----
  	{
  		res = deflate(zp, flush ? Z_FINISH : Z_NO_FLUSH);
  		if (res == Z_STREAM_ERROR)
! 			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)
*************** DeflateCompressorZlib(ArchiveHandle *AH,
*** 295,303 ****
  				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));
  			}
  			zp->next_out = (void *) out;
  			zp->avail_out = cs->zlibOutSize;
--- 295,303 ----
  				size_t		len = cs->zlibOutSize - zp->avail_out;
  
  				if (cs->writeF(AH, out, len) != len)
! 					exit_horribly(modulename,
! 								  "could not write to output file: %s\n",
! 								  strerror(errno));
  			}
  			zp->next_out = (void *) out;
  			zp->avail_out = cs->zlibOutSize;
*************** WriteDataToArchiveZlib(ArchiveHandle *AH
*** 318,324 ****
  
  	/*
  	 * we have either succeeded in writing dLen bytes or we have called
! 	 * die_horribly()
  	 */
  	return dLen;
  }
--- 318,324 ----
  
  	/*
  	 * we have either succeeded in writing dLen bytes or we have called
! 	 * exit_horribly()
  	 */
  	return dLen;
  }
*************** ReadDataFromArchiveZlib(ArchiveHandle *A
*** 361,368 ****
  
  			res = inflate(zp, 0);
  			if (res != Z_OK && res != Z_STREAM_END)
! 				die_horribly(AH, 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);
--- 361,368 ----
  
  			res = inflate(zp, 0);
  			if (res != Z_OK && res != Z_STREAM_END)
! 				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);
*************** ReadDataFromArchiveZlib(ArchiveHandle *A
*** 377,392 ****
  		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);
  
  		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);
  
  	free(buf);
  	free(out);
--- 377,392 ----
  		zp->avail_out = ZLIB_OUT_SIZE;
  		res = inflate(zp, 0);
  		if (res != Z_OK && res != Z_STREAM_END)
! 			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)
! 		exit_horribly(modulename,
! 					  "could not close compression library: %s\n", zp->msg);
  
  	free(buf);
  	free(out);
*************** WriteDataToArchiveNone(ArchiveHandle *AH
*** 426,434 ****
  	 * 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));
  	return dLen;
  }
  
--- 426,434 ----
  	 * do a check here as well...
  	 */
  	if (cs->writeF(AH, data, dLen) != dLen)
! 		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 0b24220..d9681f6 100644
*** a/src/bin/pg_dump/dumputils.c
--- b/src/bin/pg_dump/dumputils.c
*************** static void AddAcl(PQExpBuffer aclbuf, c
*** 49,54 ****
--- 49,55 ----
  #ifdef WIN32
  static bool parallel_init_done = false;
  static DWORD tls_index;
+ static DWORD mainThreadId;
  #endif
  
  void
*************** init_parallel_dump_utils(void)
*** 59,64 ****
--- 60,66 ----
  	{
  		tls_index = TlsAlloc();
  		parallel_init_done = true;
+ 		mainThreadId = GetCurrentThreadId();
  	}
  #endif
  }
*************** on_exit_nicely(on_exit_nicely_callback f
*** 1313,1318 ****
--- 1315,1327 ----
  	on_exit_nicely_index++;
  }
  
+ /* Delete any previously set callback functions */
+ void
+ on_exit_nicely_reset(void)
+ {
+ 	on_exit_nicely_index = 0;
+ }
+ 
  /* Run accumulated on_exit_nicely callbacks and then exit quietly. */
  void
  exit_nicely(int code)
*************** exit_nicely(int code)
*** 1320,1324 ****
--- 1329,1337 ----
  	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/dumputils.h b/src/bin/pg_dump/dumputils.h
index 82cf940..2865c0f 100644
*** a/src/bin/pg_dump/dumputils.h
--- b/src/bin/pg_dump/dumputils.h
*************** extern void set_section (const char *arg
*** 62,67 ****
--- 62,68 ----
  
  typedef void (*on_exit_nicely_callback) (int code, void *arg);
  extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
+ extern void on_exit_nicely_reset(void);
  extern void exit_nicely(int code) __attribute__((noreturn));
  
  #endif   /* DUMPUTILS_H */
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index ff0db46..ba553d3 100644
*** a/src/bin/pg_dump/pg_backup.h
--- b/src/bin/pg_dump/pg_backup.h
*************** extern void ConnectDatabase(Archive *AH,
*** 167,172 ****
--- 167,173 ----
  				enum trivalue prompt_password);
  extern void DisconnectDatabase(Archive *AHX);
  extern PGconn *GetConnection(Archive *AHX);
+ extern void archive_close_connection(int code, void *arg);
  
  /* Called to add a TOC entry */
  extern void ArchiveEntry(Archive *AHX,
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 79f7dda..ebf11f7 100644
*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
***************
*** 61,71 ****
--- 61,88 ----
  #define thandle HANDLE
  #endif
  
+ typedef struct _parallel_state_entry
+ {
+ #ifdef WIN32
+ 	unsigned int threadId;
+ #else
+ 	pid_t		pid;
+ #endif
+ 	ArchiveHandle *AH;
+ } ParallelStateEntry;
+ 
+ typedef struct _parallel_state
+ {
+ 	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 */
*************** static int	_discoverArchiveFormat(Archiv
*** 122,131 ****
  
  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);
--- 139,144 ----
*************** CloseArchive(Archive *AHX)
*** 208,215 ****
  		res = fclose(AH->OF);
  
  	if (res != 0)
! 		die_horribly(AH, modulename, "could not close output file: %s\n",
! 					 strerror(errno));
  }
  
  /* Public */
--- 221,228 ----
  		res = fclose(AH->OF);
  
  	if (res != 0)
! 		exit_horribly(modulename, "could not close output file: %s\n",
! 					  strerror(errno));
  }
  
  /* Public */
*************** RestoreArchive(Archive *AHX, RestoreOpti
*** 234,247 ****
  	 * 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");
  
  	/*
  	 * -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");
  
  	/*
  	 * If we're going to do parallel restore, there are some restrictions.
--- 247,260 ----
  	 * connected to, not the one we will create, which is very bad...
  	 */
  	if (ropt->createDB && ropt->dropSchema)
! 		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)
! 		exit_horribly(modulename, "-C and -1 are incompatible options\n");
  
  	/*
  	 * If we're going to do parallel restore, there are some restrictions.
*************** RestoreArchive(Archive *AHX, RestoreOpti
*** 251,261 ****
  	{
  		/* 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");
  
  		/* 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");
  
  		/*
  		 * It's also not gonna work if we can't reopen the input file, so
--- 264,274 ----
  	{
  		/* We haven't got round to making this work for all archive formats */
  		if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
! 			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)
! 			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
*************** RestoreArchive(Archive *AHX, RestoreOpti
*** 274,280 ****
  		{
  			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");
  		}
  	}
  #endif
--- 287,293 ----
  		{
  			reqs = _tocEntryRequired(te, ropt, false);
  			if (te->hadDumper && (reqs & REQ_DATA) != 0)
! 				exit_horribly(modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
  		}
  	}
  #endif
*************** RestoreArchive(Archive *AHX, RestoreOpti
*** 286,292 ****
  	{
  		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");
  
  		/* XXX Should get this from the archive */
  		AHX->minRemoteVersion = 070100;
--- 299,305 ----
  	{
  		ahlog(AH, 1, "connecting to database for restore\n");
  		if (AH->version < K_VERS_1_3)
! 			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;
*************** WriteData(Archive *AHX, const void *data
*** 734,740 ****
  	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");
  
  	return (*AH->WriteDataPtr) (AH, data, dLen);
  }
--- 747,753 ----
  	ArchiveHandle *AH = (ArchiveHandle *) AHX;
  
  	if (!AH->currToc)
! 		exit_horribly(modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
  
  	return (*AH->WriteDataPtr) (AH, data, dLen);
  }
*************** StartBlob(Archive *AHX, Oid oid)
*** 889,895 ****
  	ArchiveHandle *AH = (ArchiveHandle *) AHX;
  
  	if (!AH->StartBlobPtr)
! 		die_horribly(AH, modulename, "large-object output not supported in chosen format\n");
  
  	(*AH->StartBlobPtr) (AH, AH->currToc, oid);
  
--- 902,908 ----
  	ArchiveHandle *AH = (ArchiveHandle *) AHX;
  
  	if (!AH->StartBlobPtr)
! 		exit_horribly(modulename, "large-object output not supported in chosen format\n");
  
  	(*AH->StartBlobPtr) (AH, AH->currToc, oid);
  
*************** StartRestoreBlob(ArchiveHandle *AH, Oid
*** 976,988 ****
  		{
  			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));
  		}
  		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));
  	}
  	else
  	{
--- 989,1001 ----
  		{
  			loOid = lo_create(AH->connection, oid);
  			if (loOid == 0 || loOid != oid)
! 				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)
! 			exit_horribly(modulename, "could not open large object %u: %s",
! 						  oid, PQerrorMessage(AH->connection));
  	}
  	else
  	{
*************** SortTocFromFile(Archive *AHX, RestoreOpt
*** 1038,1045 ****
  	/* 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));
  
  	incomplete_line = false;
  	while (fgets(buf, sizeof(buf), fh) != NULL)
--- 1051,1058 ----
  	/* Setup the file */
  	fh = fopen(ropt->tocFile, PG_BINARY_R);
  	if (!fh)
! 		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)
*************** SortTocFromFile(Archive *AHX, RestoreOpt
*** 1086,1093 ****
  		/* Find TOC entry */
  		te = getTocEntryByDumpId(AH, id);
  		if (!te)
! 			die_horribly(AH, modulename, "could not find entry for ID %d\n",
! 						 id);
  
  		/* Mark it wanted */
  		ropt->idWanted[id - 1] = true;
--- 1099,1106 ----
  		/* Find TOC entry */
  		te = getTocEntryByDumpId(AH, id);
  		if (!te)
! 			exit_horribly(modulename, "could not find entry for ID %d\n",
! 						  id);
  
  		/* Mark it wanted */
  		ropt->idWanted[id - 1] = true;
*************** SortTocFromFile(Archive *AHX, RestoreOpt
*** 1107,1114 ****
  	}
  
  	if (fclose(fh) != 0)
! 		die_horribly(AH, modulename, "could not close TOC file: %s\n",
! 					 strerror(errno));
  }
  
  /*
--- 1120,1127 ----
  	}
  
  	if (fclose(fh) != 0)
! 		exit_horribly(modulename, "could not close TOC file: %s\n",
! 					  strerror(errno));
  }
  
  /*
*************** SetOutput(ArchiveHandle *AH, const char
*** 1224,1234 ****
  	if (!AH->OF)
  	{
  		if (filename)
! 			die_horribly(AH, 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));
  	}
  }
  
--- 1237,1247 ----
  	if (!AH->OF)
  	{
  		if (filename)
! 			exit_horribly(modulename, "could not open output file \"%s\": %s\n",
! 						  filename, strerror(errno));
  		else
! 			exit_horribly(modulename, "could not open output file: %s\n",
! 						  strerror(errno));
  	}
  }
  
*************** RestoreOutput(ArchiveHandle *AH, OutputC
*** 1254,1260 ****
  		res = fclose(AH->OF);
  
  	if (res != 0)
! 		die_horribly(AH, modulename, "could not close output file: %s\n",
  					 strerror(errno));
  
  	AH->gzOut = savedContext.gzOut;
--- 1267,1273 ----
  		res = fclose(AH->OF);
  
  	if (res != 0)
! 		exit_horribly(modulename, "could not close output file: %s\n",
  					 strerror(errno));
  
  	AH->gzOut = savedContext.gzOut;
*************** dump_lo_buf(ArchiveHandle *AH)
*** 1332,1338 ****
  							  AH->lo_buf_used),
  			  (unsigned long) AH->lo_buf_used, (unsigned long) res);
  		if (res != AH->lo_buf_used)
! 			die_horribly(AH, modulename,
  			"could not write to large object (result: %lu, expected: %lu)\n",
  					   (unsigned long) res, (unsigned long) AH->lo_buf_used);
  	}
--- 1345,1351 ----
  							  AH->lo_buf_used),
  			  (unsigned long) AH->lo_buf_used, (unsigned long) res);
  		if (res != AH->lo_buf_used)
! 			exit_horribly(modulename,
  			"could not write to large object (result: %lu, expected: %lu)\n",
  					   (unsigned long) res, (unsigned long) AH->lo_buf_used);
  	}
*************** ahwrite(const void *ptr, size_t size, si
*** 1391,1397 ****
  	{
  		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));
  		return res;
  	}
  	else if (AH->CustomOutPtr)
--- 1404,1410 ----
  	{
  		res = GZWRITE(ptr, size, nmemb, AH->OF);
  		if (res != (nmemb * size))
! 			exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno));
  		return res;
  	}
  	else if (AH->CustomOutPtr)
*************** ahwrite(const void *ptr, size_t size, si
*** 1399,1405 ****
  		res = AH->CustomOutPtr (AH, ptr, size * nmemb);
  
  		if (res != (nmemb * size))
! 			die_horribly(AH, modulename, "could not write to custom output routine\n");
  		return res;
  	}
  	else
--- 1412,1418 ----
  		res = AH->CustomOutPtr (AH, ptr, size * nmemb);
  
  		if (res != (nmemb * size))
! 			exit_horribly(modulename, "could not write to custom output routine\n");
  		return res;
  	}
  	else
*************** ahwrite(const void *ptr, size_t size, si
*** 1414,1468 ****
  		{
  			res = fwrite(ptr, size, nmemb, AH->OF);
  			if (res != nmemb)
! 				die_horribly(AH, 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,...)
  {
  	va_list		ap;
--- 1427,1442 ----
  		{
  			res = fwrite(ptr, size, nmemb, AH->OF);
  			if (res != nmemb)
! 				exit_horribly(modulename, "could not write to output file: %s\n",
  							 strerror(errno));
  			return res;
  		}
  	}
  }
  
  /* on some error, we may decide to go on... */
  void
! warn_or_exit_horribly(ArchiveHandle *AH,
  					 const char *modulename, const char *fmt,...)
  {
  	va_list		ap;
*************** warn_or_die_horribly(ArchiveHandle *AH,
*** 1500,1513 ****
  	AH->lastErrorTE = AH->currentTE;
  
  	va_start(ap, fmt);
  	if (AH->public.exit_on_error)
! 		vdie_horribly(AH, modulename, fmt, ap);
  	else
- 	{
- 		vwrite_msg(modulename, fmt, ap);
  		AH->public.n_errors++;
- 	}
- 	va_end(ap);
  }
  
  #ifdef NOT_USED
--- 1474,1486 ----
  	AH->lastErrorTE = AH->currentTE;
  
  	va_start(ap, fmt);
+ 	vwrite_msg(modulename, fmt, ap);
+ 	va_end(ap);
+ 
  	if (AH->public.exit_on_error)
! 		exit_nicely(1);
  	else
  		AH->public.n_errors++;
  }
  
  #ifdef NOT_USED
*************** ReadOffset(ArchiveHandle *AH, pgoff_t *
*** 1626,1632 ****
  			break;
  
  		default:
! 			die_horribly(AH, modulename, "unexpected data offset flag %d\n", offsetFlg);
  	}
  
  	/*
--- 1599,1605 ----
  			break;
  
  		default:
! 			exit_horribly(modulename, "unexpected data offset flag %d\n", offsetFlg);
  	}
  
  	/*
*************** ReadOffset(ArchiveHandle *AH, pgoff_t *
*** 1639,1645 ****
  		else
  		{
  			if ((*AH->ReadBytePtr) (AH) != 0)
! 				die_horribly(AH, modulename, "file offset in dump file is too large\n");
  		}
  	}
  
--- 1612,1618 ----
  		else
  		{
  			if ((*AH->ReadBytePtr) (AH) != 0)
! 				exit_horribly(modulename, "file offset in dump file is too large\n");
  		}
  	}
  
*************** ReadStr(ArchiveHandle *AH)
*** 1733,1739 ****
  	{
  		buf = (char *) pg_malloc(l + 1);
  		if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
! 			die_horribly(AH, modulename, "unexpected end of file\n");
  
  		buf[l] = '\0';
  	}
--- 1706,1712 ----
  	{
  		buf = (char *) pg_malloc(l + 1);
  		if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
! 			exit_horribly(modulename, "unexpected end of file\n");
  
  		buf[l] = '\0';
  	}
*************** _discoverArchiveFormat(ArchiveHandle *AH
*** 1776,1783 ****
  			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);
  			if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
  			{
  				AH->format = archDirectory;
--- 1749,1756 ----
  			char		buf[MAXPGPATH];
  
  			if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH)
! 				exit_horribly(modulename, "directory name too long: \"%s\"\n",
! 							  AH->fSpec);
  			if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
  			{
  				AH->format = archDirectory;
*************** _discoverArchiveFormat(ArchiveHandle *AH
*** 1786,1817 ****
  
  #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);
  			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);
  			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));
  		}
  	}
  	else
  	{
  		fh = stdin;
  		if (!fh)
! 			die_horribly(AH, modulename, "could not open input file: %s\n",
! 						 strerror(errno));
  	}
  
  	cnt = fread(sig, 1, 5, fh);
--- 1759,1790 ----
  
  #ifdef HAVE_LIBZ
  			if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH)
! 				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
! 			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)
! 				exit_horribly(modulename, "could not open input file \"%s\": %s\n",
! 							  AH->fSpec, strerror(errno));
  		}
  	}
  	else
  	{
  		fh = stdin;
  		if (!fh)
! 			exit_horribly(modulename, "could not open input file: %s\n",
! 						  strerror(errno));
  	}
  
  	cnt = fread(sig, 1, 5, fh);
*************** _discoverArchiveFormat(ArchiveHandle *AH
*** 1819,1828 ****
  	if (cnt != 5)
  	{
  		if (ferror(fh))
! 			die_horribly(AH, 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);
  	}
  
  	/* Save it, just in case we need it later */
--- 1792,1801 ----
  	if (cnt != 5)
  	{
  		if (ferror(fh))
! 			exit_horribly(modulename, "could not read input file: %s\n", strerror(errno));
  		else
! 			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 */
*************** _discoverArchiveFormat(ArchiveHandle *AH
*** 1883,1896 ****
  			 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");
  		}
  
  		if (AH->lookaheadLen != 512)
! 			die_horribly(AH, 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");
  
  		AH->format = archTar;
  	}
--- 1856,1869 ----
  			 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 */
! 			exit_horribly(modulename, "input file appears to be a text format dump. Please use psql.\n");
  		}
  
  		if (AH->lookaheadLen != 512)
! 			exit_horribly(modulename, "input file does not appear to be a valid archive (too short?)\n");
  
  		if (!isValidTarHeader(AH->lookahead))
! 			exit_horribly(modulename, "input file does not appear to be a valid archive\n");
  
  		AH->format = archTar;
  	}
*************** _discoverArchiveFormat(ArchiveHandle *AH
*** 1910,1917 ****
  	/* Close the file */
  	if (wantClose)
  		if (fclose(fh) != 0)
! 			die_horribly(AH, modulename, "could not close input file: %s\n",
! 						 strerror(errno));
  
  	return AH->format;
  }
--- 1883,1890 ----
  	/* Close the file */
  	if (wantClose)
  		if (fclose(fh) != 0)
! 			exit_horribly(modulename, "could not close input file: %s\n",
! 						  strerror(errno));
  
  	return AH->format;
  }
*************** _allocAH(const char *FileSpec, const Arc
*** 2034,2040 ****
  			break;
  
  		default:
! 			die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
  	}
  
  	return AH;
--- 2007,2013 ----
  			break;
  
  		default:
! 			exit_horribly(modulename, "unrecognized file format \"%d\"\n", fmt);
  	}
  
  	return AH;
*************** ReadToc(ArchiveHandle *AH)
*** 2156,2164 ****
  
  		/* Sanity check */
  		if (te->dumpId <= 0)
! 			die_horribly(AH, modulename,
! 					   "entry ID %d out of range -- perhaps a corrupt TOC\n",
! 						 te->dumpId);
  
  		te->hadDumper = ReadInt(AH);
  
--- 2129,2137 ----
  
  		/* Sanity check */
  		if (te->dumpId <= 0)
! 			exit_horribly(modulename,
! 						  "entry ID %d out of range -- perhaps a corrupt TOC\n",
! 						  te->dumpId);
  
  		te->hadDumper = ReadInt(AH);
  
*************** processEncodingEntry(ArchiveHandle *AH,
*** 2313,2325 ****
  		*ptr2 = '\0';
  		encoding = pg_char_to_encoding(ptr1);
  		if (encoding < 0)
! 			die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
! 						 ptr1);
  		AH->public.encoding = encoding;
  	}
  	else
! 		die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
! 					 te->defn);
  
  	free(defn);
  }
--- 2286,2298 ----
  		*ptr2 = '\0';
  		encoding = pg_char_to_encoding(ptr1);
  		if (encoding < 0)
! 			exit_horribly(modulename, "unrecognized encoding \"%s\"\n",
! 						  ptr1);
  		AH->public.encoding = encoding;
  	}
  	else
! 		exit_horribly(modulename, "invalid ENCODING item: %s\n",
! 					  te->defn);
  
  	free(defn);
  }
*************** processStdStringsEntry(ArchiveHandle *AH
*** 2336,2343 ****
  	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);
  }
  
  static teReqs
--- 2309,2316 ----
  	else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
  		AH->public.std_strings = false;
  	else
! 		exit_horribly(modulename, "invalid STDSTRINGS item: %s\n",
! 					  te->defn);
  }
  
  static teReqs
*************** _doSetSessionAuth(ArchiveHandle *AH, con
*** 2544,2552 ****
  		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));
  
  		PQclear(res);
  	}
--- 2517,2525 ----
  		res = PQexec(AH->connection, cmd->data);
  
  		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
! 			/* 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);
  	}
*************** _doSetWithOids(ArchiveHandle *AH, const
*** 2576,2584 ****
  		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));
  
  		PQclear(res);
  	}
--- 2549,2557 ----
  		res = PQexec(AH->connection, cmd->data);
  
  		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
! 			warn_or_exit_horribly(AH, modulename,
! 								  "could not set default_with_oids: %s",
! 								  PQerrorMessage(AH->connection));
  
  		PQclear(res);
  	}
*************** _selectOutputSchema(ArchiveHandle *AH, c
*** 2714,2722 ****
  		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));
  
  		PQclear(res);
  	}
--- 2687,2695 ----
  		res = PQexec(AH->connection, qry->data);
  
  		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
! 			warn_or_exit_horribly(AH, modulename,
! 								  "could not set search_path to \"%s\": %s",
! 								  schemaName, PQerrorMessage(AH->connection));
  
  		PQclear(res);
  	}
*************** _selectTablespace(ArchiveHandle *AH, con
*** 2775,2783 ****
  		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));
  
  		PQclear(res);
  	}
--- 2748,2756 ----
  		res = PQexec(AH->connection, qry->data);
  
  		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
! 			warn_or_exit_horribly(AH, modulename,
! 								  "could not set default_tablespace to %s: %s",
! 								  fmtId(want), PQerrorMessage(AH->connection));
  
  		PQclear(res);
  	}
*************** ReadHead(ArchiveHandle *AH)
*** 3157,3166 ****
  	if (!AH->readHeader)
  	{
  		if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5)
! 			die_horribly(AH, 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");
  
  		AH->vmaj = (*AH->ReadBytePtr) (AH);
  		AH->vmin = (*AH->ReadBytePtr) (AH);
--- 3130,3139 ----
  	if (!AH->readHeader)
  	{
  		if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5)
! 			exit_horribly(modulename, "unexpected end of file\n");
  
  		if (strncmp(tmpMag, "PGDMP", 5) != 0)
! 			exit_horribly(modulename, "did not find magic string in file header\n");
  
  		AH->vmaj = (*AH->ReadBytePtr) (AH);
  		AH->vmin = (*AH->ReadBytePtr) (AH);
*************** ReadHead(ArchiveHandle *AH)
*** 3173,3185 ****
  		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);
  
  		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);
  
  		if (AH->intSize > sizeof(int))
  			write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
--- 3146,3158 ----
  		AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
  
  		if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
! 			exit_horribly(modulename, "unsupported version (%d.%d) in file header\n",
! 						  AH->vmaj, AH->vmin);
  
  		AH->intSize = (*AH->ReadBytePtr) (AH);
  		if (AH->intSize > 32)
! 			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");
*************** ReadHead(ArchiveHandle *AH)
*** 3192,3199 ****
  		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);
  	}
  
  	if (AH->version >= K_VERS_1_2)
--- 3165,3172 ----
  		fmt = (*AH->ReadBytePtr) (AH);
  
  		if (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)
*************** dumpTimestamp(ArchiveHandle *AH, const c
*** 3297,3302 ****
--- 3270,3321 ----
  		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 int
+ GetMySlot(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 i;
+ 
+ 	return NO_SLOT;
+ }
+ 
+ static void
+ archive_close_connection_parallel(int code, void *ps)
+ {
+ 	ParallelState *pstate = (ParallelState *) ps;
+ 	int slotno = GetMySlot(pstate);
+ 	if (slotno != NO_SLOT && pstate->pse[slotno].AH)
+ 		DisconnectDatabase(&pstate->pse[slotno].AH->public);
+ }
  
  /*
   * Main engine for parallel restore.
*************** restore_toc_entries_parallel(ArchiveHand
*** 3323,3332 ****
  	TocEntry   *next_work_item;
  	thandle		ret_child;
  	TocEntry   *te;
  
  	ahlog(AH, 2, "entering restore_toc_entries_parallel\n");
  
! 	slots = (ParallelSlot *) pg_calloc(sizeof(ParallelSlot), n_slots);
  
  	/* Adjust dependency information */
  	fix_dependencies(AH);
--- 3342,3358 ----
  	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(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);
*************** restore_toc_entries_parallel(ArchiveHand
*** 3382,3387 ****
--- 3408,3420 ----
  	 */
  	DisconnectDatabase(&AH->public);
  
+ 	/*
+ 	 * Both pg_dump and pg_restore that use this code set at most
+ 	 * one exit handler. So we can just reset the handlers.
+ 	 */
+ 	on_exit_nicely_reset();
+ 	on_exit_nicely(archive_close_connection_parallel, pstate);
+ 
  	/* blow away any transient state from the old connection */
  	if (AH->currUser)
  		free(AH->currUser);
*************** restore_toc_entries_parallel(ArchiveHand
*** 3480,3485 ****
--- 3513,3519 ----
  				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);
*************** restore_toc_entries_parallel(ArchiveHand
*** 3507,3518 ****
  		}
  		else
  		{
! 			die_horribly(AH, modulename, "worker process crashed: status %d\n",
! 						 work_status);
  		}
  	}
  
  	ahlog(AH, 1, "finished main parallel loop\n");
  
  	/*
  	 * Now reconnect the single parent connection.
--- 3541,3554 ----
  		}
  		else
  		{
! 			exit_horribly(modulename, "worker process crashed: status %d\n",
! 						  work_status);
  		}
  	}
  
  	ahlog(AH, 1, "finished main parallel loop\n");
+ 	on_exit_nicely_reset();
+ 	on_exit_nicely(archive_close_connection, AH);
  
  	/*
  	 * Now reconnect the single parent connection.
*************** spawn_restore(RestoreArgs *args)
*** 3555,3577 ****
  	{
  		/* in child process */
  		parallel_restore(args);
! 		die_horribly(args->AH, 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));
  	}
  #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));
  #endif
  
  	return child;
--- 3591,3613 ----
  	{
  		/* in child process */
  		parallel_restore(args);
! 		exit_horribly(modulename,
! 					  "parallel_restore should not return\n");
  	}
  	else if (child < 0)
  	{
  		/* fork failed */
! 		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)
! 		exit_horribly(modulename,
! 					  "could not create worker thread: %s\n",
! 					  strerror(errno));
  #endif
  
  	return child;
*************** parallel_restore(RestoreArgs *args)
*** 3813,3818 ****
--- 3849,3856 ----
  	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
*************** parallel_restore(RestoreArgs *args)
*** 3843,3848 ****
--- 3881,3887 ----
  
  	/* 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)
*************** mark_work_done(ArchiveHandle *AH, TocEnt
*** 3888,3894 ****
  	}
  
  	if (te == NULL)
! 		die_horribly(AH, modulename, "could not find slot of finished worker\n");
  
  	ahlog(AH, 1, "finished item %d %s %s\n",
  		  te->dumpId, te->desc, te->tag);
--- 3927,3933 ----
  	}
  
  	if (te == NULL)
! 		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);
*************** mark_work_done(ArchiveHandle *AH, TocEnt
*** 3903,3910 ****
  	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);
  
  	reduce_dependencies(AH, te, ready_list);
  }
--- 3942,3949 ----
  	else if (status == WORKER_IGNORED_ERRORS)
  		AH->public.n_errors++;
  	else if (status != 0)
! 		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 fa8c58c..b29d0f1 100644
*** a/src/bin/pg_dump/pg_backup_archiver.h
--- b/src/bin/pg_dump/pg_backup_archiver.h
*************** typedef struct _tocEntry
*** 324,332 ****
  } TocEntry;
  
  
! 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 WriteTOC(ArchiveHandle *AH);
  extern void ReadTOC(ArchiveHandle *AH);
--- 324,330 ----
  } TocEntry;
  
  
! 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 31fa373..87242c5 100644
*** a/src/bin/pg_dump/pg_backup_custom.c
--- b/src/bin/pg_dump/pg_backup_custom.c
*************** InitArchiveFmt_Custom(ArchiveHandle *AH)
*** 146,160 ****
  		{
  			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));
  		}
  		else
  		{
  			AH->FH = stdout;
  			if (!AH->FH)
! 				die_horribly(AH, modulename, "could not open output file: %s\n",
! 							 strerror(errno));
  		}
  
  		ctx->hasSeek = checkSeek(AH->FH);
--- 146,160 ----
  		{
  			AH->FH = fopen(AH->fSpec, PG_BINARY_W);
  			if (!AH->FH)
! 				exit_horribly(modulename, "could not open output file \"%s\": %s\n",
! 							  AH->fSpec, strerror(errno));
  		}
  		else
  		{
  			AH->FH = stdout;
  			if (!AH->FH)
! 				exit_horribly(modulename, "could not open output file: %s\n",
! 							  strerror(errno));
  		}
  
  		ctx->hasSeek = checkSeek(AH->FH);
*************** InitArchiveFmt_Custom(ArchiveHandle *AH)
*** 165,179 ****
  		{
  			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));
  		}
  		else
  		{
  			AH->FH = stdin;
  			if (!AH->FH)
! 				die_horribly(AH, modulename, "could not open input file: %s\n",
! 							 strerror(errno));
  		}
  
  		ctx->hasSeek = checkSeek(AH->FH);
--- 165,179 ----
  		{
  			AH->FH = fopen(AH->fSpec, PG_BINARY_R);
  			if (!AH->FH)
! 				exit_horribly(modulename, "could not open input file \"%s\": %s\n",
! 							  AH->fSpec, strerror(errno));
  		}
  		else
  		{
  			AH->FH = stdin;
  			if (!AH->FH)
! 				exit_horribly(modulename, "could not open input file: %s\n",
! 							  strerror(errno));
  		}
  
  		ctx->hasSeek = checkSeek(AH->FH);
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 367,373 ****
  	lclContext *ctx = (lclContext *) AH->formatData;
  
  	if (oid == 0)
! 		die_horribly(AH, modulename, "invalid OID for large object\n");
  
  	WriteInt(AH, oid);
  
--- 367,373 ----
  	lclContext *ctx = (lclContext *) AH->formatData;
  
  	if (oid == 0)
! 		exit_horribly(modulename, "invalid OID for large object\n");
  
  	WriteInt(AH, oid);
  
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 437,445 ****
  					break;
  
  				default:		/* Always have a default */
! 					die_horribly(AH, modulename,
! 								 "unrecognized data block type (%d) while searching archive\n",
! 								 blkType);
  					break;
  			}
  			_readBlockHeader(AH, &blkType, &id);
--- 437,445 ----
  					break;
  
  				default:		/* Always have a default */
! 					exit_horribly(modulename,
! 								  "unrecognized data block type (%d) while searching archive\n",
! 								  blkType);
  					break;
  			}
  			_readBlockHeader(AH, &blkType, &id);
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 449,456 ****
  	{
  		/* 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));
  
  		_readBlockHeader(AH, &blkType, &id);
  	}
--- 449,456 ----
  	{
  		/* We can just seek to the place we need to be. */
  		if (fseeko(AH->FH, tctx->dataPos, SEEK_SET) != 0)
! 			exit_horribly(modulename, "error during file seek: %s\n",
! 						  strerror(errno));
  
  		_readBlockHeader(AH, &blkType, &id);
  	}
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 459,483 ****
  	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);
  		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);
  		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);
  	}
  
  	/* 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);
  
  	switch (blkType)
  	{
--- 459,483 ----
  	if (blkType == EOF)
  	{
  		if (tctx->dataState == K_OFFSET_POS_NOT_SET)
! 			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)
! 			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? */
! 			exit_horribly(modulename, "could not find block ID %d in archive -- "
! 						  "possibly corrupt archive\n",
! 						  te->dumpId);
  	}
  
  	/* Are we sane? */
  	if (id != te->dumpId)
! 		exit_horribly(modulename, "found unexpected block ID (%d) when reading data -- expected %d\n",
! 					  id, te->dumpId);
  
  	switch (blkType)
  	{
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 490,497 ****
  			break;
  
  		default:				/* Always have a default */
! 			die_horribly(AH, modulename, "unrecognized data block type %d while restoring archive\n",
! 						 blkType);
  			break;
  	}
  }
--- 490,497 ----
  			break;
  
  		default:				/* Always have a default */
! 			exit_horribly(modulename, "unrecognized data block type %d while restoring archive\n",
! 						  blkType);
  			break;
  	}
  }
*************** _skipData(ArchiveHandle *AH)
*** 571,581 ****
  		if (cnt != blkLen)
  		{
  			if (feof(AH->FH))
! 				die_horribly(AH, 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));
  		}
  
  		ctx->filePos += blkLen;
--- 571,581 ----
  		if (cnt != blkLen)
  		{
  			if (feof(AH->FH))
! 				exit_horribly(modulename,
! 							  "could not read from input file: end of file\n");
  			else
! 				exit_horribly(modulename,
! 							  "could not read from input file: %s\n", strerror(errno));
  		}
  
  		ctx->filePos += blkLen;
*************** _WriteByte(ArchiveHandle *AH, const int
*** 604,610 ****
  	if (res != EOF)
  		ctx->filePos += 1;
  	else
! 		die_horribly(AH, modulename, "could not write byte: %s\n", strerror(errno));
  	return res;
  }
  
--- 604,610 ----
  	if (res != EOF)
  		ctx->filePos += 1;
  	else
! 		exit_horribly(modulename, "could not write byte: %s\n", strerror(errno));
  	return res;
  }
  
*************** _ReadByte(ArchiveHandle *AH)
*** 624,630 ****
  
  	res = getc(AH->FH);
  	if (res == EOF)
! 		die_horribly(AH, modulename, "unexpected end of file\n");
  	ctx->filePos += 1;
  	return res;
  }
--- 624,630 ----
  
  	res = getc(AH->FH);
  	if (res == EOF)
! 		exit_horribly(modulename, "unexpected end of file\n");
  	ctx->filePos += 1;
  	return res;
  }
*************** _WriteBuf(ArchiveHandle *AH, const void
*** 645,651 ****
  	res = fwrite(buf, 1, len, AH->FH);
  
  	if (res != len)
! 		die_horribly(AH, modulename,
  					 "could not write to output file: %s\n", strerror(errno));
  
  	ctx->filePos += res;
--- 645,651 ----
  	res = fwrite(buf, 1, len, AH->FH);
  
  	if (res != len)
! 		exit_horribly(modulename,
  					 "could not write to output file: %s\n", strerror(errno));
  
  	ctx->filePos += res;
*************** _CloseArchive(ArchiveHandle *AH)
*** 712,718 ****
  	}
  
  	if (fclose(AH->FH) != 0)
! 		die_horribly(AH, modulename, "could not close archive file: %s\n", strerror(errno));
  
  	AH->FH = NULL;
  }
--- 712,718 ----
  	}
  
  	if (fclose(AH->FH) != 0)
! 		exit_horribly(modulename, "could not close archive file: %s\n", strerror(errno));
  
  	AH->FH = NULL;
  }
*************** _ReopenArchive(ArchiveHandle *AH)
*** 731,767 ****
  	pgoff_t		tpos;
  
  	if (AH->mode == archModeWrite)
! 		die_horribly(AH, 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");
  	if (!ctx->hasSeek)
! 		die_horribly(AH, 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));
  
  #ifndef WIN32
  	if (fclose(AH->FH) != 0)
! 		die_horribly(AH, 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));
  
  	if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
! 		die_horribly(AH, modulename, "could not set seek position in archive file: %s\n",
! 					 strerror(errno));
  }
  
  /*
--- 731,767 ----
  	pgoff_t		tpos;
  
  	if (AH->mode == archModeWrite)
! 		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)
! 		exit_horribly(modulename, "parallel restore from stdin is not supported\n");
  	if (!ctx->hasSeek)
! 		exit_horribly(modulename, "parallel restore from non-seekable file is not supported\n");
  
  	errno = 0;
  	tpos = ftello(AH->FH);
  	if (errno)
! 		exit_horribly(modulename, "could not determine seek position in archive file: %s\n",
! 					  strerror(errno));
  
  #ifndef WIN32
  	if (fclose(AH->FH) != 0)
! 		exit_horribly(modulename, "could not close archive file: %s\n",
! 					  strerror(errno));
  #endif
  
  	AH->FH = fopen(AH->fSpec, PG_BINARY_R);
  	if (!AH->FH)
! 		exit_horribly(modulename, "could not open input file \"%s\": %s\n",
! 					  AH->fSpec, strerror(errno));
  
  	if (fseeko(AH->FH, tpos, SEEK_SET) != 0)
! 		exit_horribly(modulename, "could not set seek position in archive file: %s\n",
! 					  strerror(errno));
  }
  
  /*
*************** _Clone(ArchiveHandle *AH)
*** 778,784 ****
  
  	/* sanity check, shouldn't happen */
  	if (ctx->cs != NULL)
! 		die_horribly(AH, modulename, "compressor active\n");
  
  	/*
  	 * Note: we do not make a local lo_buf because we expect at most one BLOBS
--- 778,784 ----
  
  	/* sanity check, shouldn't happen */
  	if (ctx->cs != NULL)
! 		exit_horribly(modulename, "compressor active\n");
  
  	/*
  	 * Note: we do not make a local lo_buf because we expect at most one BLOBS
*************** _readBlockHeader(ArchiveHandle *AH, int
*** 840,846 ****
  	int			byt;
  
  	/*
! 	 * Note: if we are at EOF with a pre-1.3 input file, we'll die_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
--- 840,846 ----
  	int			byt;
  
  	/*
! 	 * 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
*************** _CustomReadFunc(ArchiveHandle *AH, char
*** 905,914 ****
  	if (cnt != blkLen)
  	{
  		if (feof(AH->FH))
! 			die_horribly(AH, 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));
  	}
  	return cnt;
--- 905,914 ----
  	if (cnt != blkLen)
  	{
  		if (feof(AH->FH))
! 			exit_horribly(modulename,
! 						  "could not read from input file: end of file\n");
  		else
! 			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 a843eac..4a8283a 100644
*** a/src/bin/pg_dump/pg_backup_db.c
--- b/src/bin/pg_dump/pg_backup_db.c
*************** static PGconn *_connectDB(ArchiveHandle
*** 30,42 ****
  static void notice_processor(void *arg, const char *message);
  
  static int
! _parse_version(ArchiveHandle *AH, const char *versionString)
  {
  	int			v;
  
  	v = parse_version(versionString);
  	if (v < 0)
! 		die_horribly(AH, modulename, "could not parse version string \"%s\"\n", versionString);
  
  	return v;
  }
--- 30,42 ----
  static void notice_processor(void *arg, const char *message);
  
  static int
! _parse_version(const char *versionString)
  {
  	int			v;
  
  	v = parse_version(versionString);
  	if (v < 0)
! 		exit_horribly(modulename, "could not parse version string \"%s\"\n", versionString);
  
  	return v;
  }
*************** _check_database_version(ArchiveHandle *A
*** 48,60 ****
  	const char *remoteversion_str;
  	int			remoteversion;
  
! 	myversion = _parse_version(AH, PG_VERSION);
  
  	remoteversion_str = PQparameterStatus(AH->connection, "server_version");
  	if (!remoteversion_str)
! 		die_horribly(AH, modulename, "could not get server_version from libpq\n");
  
! 	remoteversion = _parse_version(AH, remoteversion_str);
  
  	AH->public.remoteVersionStr = pg_strdup(remoteversion_str);
  	AH->public.remoteVersion = remoteversion;
--- 48,60 ----
  	const char *remoteversion_str;
  	int			remoteversion;
  
! 	myversion = _parse_version(PG_VERSION);
  
  	remoteversion_str = PQparameterStatus(AH->connection, "server_version");
  	if (!remoteversion_str)
! 		exit_horribly(modulename, "could not get server_version from libpq\n");
  
! 	remoteversion = _parse_version(remoteversion_str);
  
  	AH->public.remoteVersionStr = pg_strdup(remoteversion_str);
  	AH->public.remoteVersion = remoteversion;
*************** _check_database_version(ArchiveHandle *A
*** 67,73 ****
  	{
  		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");
  	}
  }
  
--- 67,73 ----
  	{
  		write_msg(NULL, "server version: %s; %s version: %s\n",
  				  remoteversion_str, progname, PG_VERSION);
! 		exit_horribly(NULL, "aborting because of server version mismatch\n");
  	}
  }
  
*************** _connectDB(ArchiveHandle *AH, const char
*** 145,151 ****
  	{
  		password = simple_prompt("Password: ", 100, false);
  		if (password == NULL)
! 			die_horribly(AH, modulename, "out of memory\n");
  	}
  
  	do
--- 145,151 ----
  	{
  		password = simple_prompt("Password: ", 100, false);
  		if (password == NULL)
! 			exit_horribly(modulename, "out of memory\n");
  	}
  
  	do
*************** _connectDB(ArchiveHandle *AH, const char
*** 176,187 ****
  		free(values);
  
  		if (!newConn)
! 			die_horribly(AH, 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",
  							 PQerrorMessage(newConn));
  			PQfinish(newConn);
  
--- 176,187 ----
  		free(values);
  
  		if (!newConn)
! 			exit_horribly(modulename, "failed to reconnect to database\n");
  
  		if (PQstatus(newConn) == CONNECTION_BAD)
  		{
  			if (!PQconnectionNeedsPassword(newConn))
! 				exit_horribly(modulename, "could not reconnect to database: %s",
  							 PQerrorMessage(newConn));
  			PQfinish(newConn);
  
*************** _connectDB(ArchiveHandle *AH, const char
*** 197,206 ****
  			if (AH->promptPassword != TRI_NO)
  				password = simple_prompt("Password: ", 100, false);
  			else
! 				die_horribly(AH, modulename, "connection needs password\n");
  
  			if (password == NULL)
! 				die_horribly(AH, modulename, "out of memory\n");
  			new_pass = true;
  		}
  	} while (new_pass);
--- 197,206 ----
  			if (AH->promptPassword != TRI_NO)
  				password = simple_prompt("Password: ", 100, false);
  			else
! 				exit_horribly(modulename, "connection needs password\n");
  
  			if (password == NULL)
! 				exit_horribly(modulename, "out of memory\n");
  			new_pass = true;
  		}
  	} while (new_pass);
*************** ConnectDatabase(Archive *AHX,
*** 238,250 ****
  	bool		new_pass;
  
  	if (AH->connection)
! 		die_horribly(AH, 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");
  	}
  	AH->promptPassword = prompt_password;
  
--- 238,250 ----
  	bool		new_pass;
  
  	if (AH->connection)
! 		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)
! 			exit_horribly(modulename, "out of memory\n");
  	}
  	AH->promptPassword = prompt_password;
  
*************** ConnectDatabase(Archive *AHX,
*** 280,286 ****
  		free(values);
  
  		if (!AH->connection)
! 			die_horribly(AH, modulename, "failed to connect to database\n");
  
  		if (PQstatus(AH->connection) == CONNECTION_BAD &&
  			PQconnectionNeedsPassword(AH->connection) &&
--- 280,286 ----
  		free(values);
  
  		if (!AH->connection)
! 			exit_horribly(modulename, "failed to connect to database\n");
  
  		if (PQstatus(AH->connection) == CONNECTION_BAD &&
  			PQconnectionNeedsPassword(AH->connection) &&
*************** ConnectDatabase(Archive *AHX,
*** 290,296 ****
  			PQfinish(AH->connection);
  			password = simple_prompt("Password: ", 100, false);
  			if (password == NULL)
! 				die_horribly(AH, modulename, "out of memory\n");
  			new_pass = true;
  		}
  	} while (new_pass);
--- 290,296 ----
  			PQfinish(AH->connection);
  			password = simple_prompt("Password: ", 100, false);
  			if (password == NULL)
! 				exit_horribly(modulename, "out of memory\n");
  			new_pass = true;
  		}
  	} while (new_pass);
*************** ConnectDatabase(Archive *AHX,
*** 299,305 ****
  
  	/* 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",
  					 PQdb(AH->connection), PQerrorMessage(AH->connection));
  
  	/* check for version mismatch */
--- 299,305 ----
  
  	/* check to see that the backend connection was successfully made */
  	if (PQstatus(AH->connection) == CONNECTION_BAD)
! 		exit_horribly(modulename, "connection to database \"%s\" failed: %s",
  					 PQdb(AH->connection), PQerrorMessage(AH->connection));
  
  	/* check for version mismatch */
*************** GetConnection(Archive *AHX)
*** 325,336 ****
--- 325,352 ----
  	return AH->connection;
  }
  
+ void
+ archive_close_connection(int code, void *arg)
+ {
+ 	Archive	   *AH = (Archive *) arg;
+ 
+ 	DisconnectDatabase(AH);
+ }
+ 
  static void
  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)
*************** ExecuteSqlCommand(ArchiveHandle *AH, con
*** 393,400 ****
  				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);
  			break;
  	}
  
--- 409,416 ----
  				errStmt[DB_MAX_ERR_STMT - 2] = '.';
  				errStmt[DB_MAX_ERR_STMT - 1] = '\0';
  			}
! 			warn_or_exit_horribly(AH, modulename, "%s: %s    Command was: %s\n",
! 								  desc, PQerrorMessage(conn), errStmt);
  			break;
  	}
  
*************** ExecuteSqlCommandBuf(ArchiveHandle *AH,
*** 495,502 ****
  		 */
  		if (AH->pgCopyIn &&
  			PQputCopyData(AH->connection, buf, bufLen) <= 0)
! 			die_horribly(AH, modulename, "error returned by PQputCopyData: %s",
! 						 PQerrorMessage(AH->connection));
  	}
  	else if (AH->outputKind == OUTPUT_OTHERDATA)
  	{
--- 511,518 ----
  		 */
  		if (AH->pgCopyIn &&
  			PQputCopyData(AH->connection, buf, bufLen) <= 0)
! 			exit_horribly(modulename, "error returned by PQputCopyData: %s",
! 						  PQerrorMessage(AH->connection));
  	}
  	else if (AH->outputKind == OUTPUT_OTHERDATA)
  	{
*************** EndDBCopyMode(ArchiveHandle *AH, TocEntr
*** 541,554 ****
  		PGresult   *res;
  
  		if (PQputCopyEnd(AH->connection, NULL) <= 0)
! 			die_horribly(AH, 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));
  		PQclear(res);
  
  		AH->pgCopyIn = false;
--- 557,570 ----
  		PGresult   *res;
  
  		if (PQputCopyEnd(AH->connection, NULL) <= 0)
! 			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_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 4b59516..8d43cd2 100644
*** a/src/bin/pg_dump/pg_backup_directory.c
--- b/src/bin/pg_dump/pg_backup_directory.c
*************** InitArchiveFmt_Directory(ArchiveHandle *
*** 142,148 ****
  	 */
  
  	if (!AH->fSpec || strcmp(AH->fSpec, "") == 0)
! 		die_horribly(AH, modulename, "no output directory specified\n");
  
  	ctx->directory = AH->fSpec;
  
--- 142,148 ----
  	 */
  
  	if (!AH->fSpec || strcmp(AH->fSpec, "") == 0)
! 		exit_horribly(modulename, "no output directory specified\n");
  
  	ctx->directory = AH->fSpec;
  
*************** InitArchiveFmt_Directory(ArchiveHandle *
*** 160,168 ****
  
  		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));
  
  		ctx->dataFH = tocFH;
  
--- 160,168 ----
  
  		tocFH = cfopen_read(fname, PG_BINARY_R);
  		if (tocFH == NULL)
! 			exit_horribly(modulename,
! 						  "could not open input file \"%s\": %s\n",
! 						  fname, strerror(errno));
  
  		ctx->dataFH = tocFH;
  
*************** InitArchiveFmt_Directory(ArchiveHandle *
*** 177,183 ****
  
  		/* Nothing else in the file, so close it again... */
  		if (cfclose(tocFH) != 0)
! 			die_horribly(AH, modulename, "could not close TOC file: %s\n",
  						 strerror(errno));
  		ctx->dataFH = NULL;
  	}
--- 177,183 ----
  
  		/* Nothing else in the file, so close it again... */
  		if (cfclose(tocFH) != 0)
! 			exit_horribly(modulename, "could not close TOC file: %s\n",
  						 strerror(errno));
  		ctx->dataFH = NULL;
  	}
*************** _StartData(ArchiveHandle *AH, TocEntry *
*** 288,295 ****
  
  	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));
  }
  
  /*
--- 288,295 ----
  
  	ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
  	if (ctx->dataFH == NULL)
! 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
! 					  fname, strerror(errno));
  }
  
  /*
*************** _PrintFileData(ArchiveHandle *AH, char *
*** 346,352 ****
  	cfp = cfopen_read(filename, PG_BINARY_R);
  
  	if (!cfp)
! 		die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
  					 filename, strerror(errno));
  
  	buf = pg_malloc(ZLIB_OUT_SIZE);
--- 346,352 ----
  	cfp = cfopen_read(filename, PG_BINARY_R);
  
  	if (!cfp)
! 		exit_horribly(modulename, "could not open input file \"%s\": %s\n",
  					 filename, strerror(errno));
  
  	buf = pg_malloc(ZLIB_OUT_SIZE);
*************** _PrintFileData(ArchiveHandle *AH, char *
*** 357,363 ****
  
  	free(buf);
  	if (cfclose(cfp) != 0)
! 		die_horribly(AH, modulename, "could not close data file: %s\n",
  					 strerror(errno));
  }
  
--- 357,363 ----
  
  	free(buf);
  	if (cfclose(cfp) != 0)
! 		exit_horribly(modulename, "could not close data file: %s\n",
  					 strerror(errno));
  }
  
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 397,404 ****
  	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));
  
  	/* Read the blobs TOC file line-by-line, and process each blob */
  	while ((cfgets(ctx->blobsTocFH, line, MAXPGPATH)) != NULL)
--- 397,404 ----
  	ctx->blobsTocFH = cfopen_read(fname, PG_BINARY_R);
  
  	if (ctx->blobsTocFH == NULL)
! 		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)
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 407,414 ****
  		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);
  
  		StartRestoreBlob(AH, oid, ropt->dropSchema);
  		snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, fname);
--- 407,414 ----
  		char		path[MAXPGPATH];
  
  		if (sscanf(line, "%u %s\n", &oid, fname) != 2)
! 			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);
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 416,427 ****
  		EndRestoreBlob(AH, oid);
  	}
  	if (!cfeof(ctx->blobsTocFH))
! 		die_horribly(AH, 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));
  
  	ctx->blobsTocFH = NULL;
  
--- 416,427 ----
  		EndRestoreBlob(AH, oid);
  	}
  	if (!cfeof(ctx->blobsTocFH))
! 		exit_horribly(modulename, "error reading large object TOC file \"%s\"\n",
  					 fname);
  
  	if (cfclose(ctx->blobsTocFH) != 0)
! 		exit_horribly(modulename, "could not close large object TOC file \"%s\": %s\n",
! 					  fname, strerror(errno));
  
  	ctx->blobsTocFH = NULL;
  
*************** _WriteByte(ArchiveHandle *AH, const int
*** 441,447 ****
  	lclContext *ctx = (lclContext *) AH->formatData;
  
  	if (cfwrite(&c, 1, ctx->dataFH) != 1)
! 		die_horribly(AH, modulename, "could not write byte\n");
  
  	return 1;
  }
--- 441,447 ----
  	lclContext *ctx = (lclContext *) AH->formatData;
  
  	if (cfwrite(&c, 1, ctx->dataFH) != 1)
! 		exit_horribly(modulename, "could not write byte\n");
  
  	return 1;
  }
*************** _ReadByte(ArchiveHandle *AH)
*** 460,466 ****
  
  	res = cfgetc(ctx->dataFH);
  	if (res == EOF)
! 		die_horribly(AH, modulename, "unexpected end of file\n");
  
  	return res;
  }
--- 460,466 ----
  
  	res = cfgetc(ctx->dataFH);
  	if (res == EOF)
! 		exit_horribly(modulename, "unexpected end of file\n");
  
  	return res;
  }
*************** _WriteBuf(ArchiveHandle *AH, const void
*** 477,483 ****
  
  	res = cfwrite(buf, len, ctx->dataFH);
  	if (res != len)
! 		die_horribly(AH, modulename, "could not write to output file: %s\n",
  					 strerror(errno));
  
  	return res;
--- 477,483 ----
  
  	res = cfwrite(buf, len, ctx->dataFH);
  	if (res != len)
! 		exit_horribly(modulename, "could not write to output file: %s\n",
  					 strerror(errno));
  
  	return res;
*************** _CloseArchive(ArchiveHandle *AH)
*** 524,531 ****
  		/* 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));
  		ctx->dataFH = tocFH;
  
  		/*
--- 524,531 ----
  		/* The TOC is always created uncompressed */
  		tocFH = cfopen_write(fname, PG_BINARY_W, 0);
  		if (tocFH == NULL)
! 			exit_horribly(modulename, "could not open output file \"%s\": %s\n",
! 						  fname, strerror(errno));
  		ctx->dataFH = tocFH;
  
  		/*
*************** _CloseArchive(ArchiveHandle *AH)
*** 538,545 ****
  		AH->format = archDirectory;
  		WriteToc(AH);
  		if (cfclose(tocFH) != 0)
! 			die_horribly(AH, modulename, "could not close TOC file: %s\n",
! 						 strerror(errno));
  		WriteDataChunks(AH);
  	}
  	AH->FH = NULL;
--- 538,545 ----
  		AH->format = archDirectory;
  		WriteToc(AH);
  		if (cfclose(tocFH) != 0)
! 			exit_horribly(modulename, "could not close TOC file: %s\n",
! 						  strerror(errno));
  		WriteDataChunks(AH);
  	}
  	AH->FH = NULL;
*************** _StartBlobs(ArchiveHandle *AH, TocEntry
*** 568,575 ****
  	/* 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));
  }
  
  /*
--- 568,575 ----
  	/* The blob TOC file is never compressed */
  	ctx->blobsTocFH = cfopen_write(fname, "ab", 0);
  	if (ctx->blobsTocFH == NULL)
! 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
! 					  fname, strerror(errno));
  }
  
  /*
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 588,594 ****
  	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));
  }
  
--- 588,594 ----
  	ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression);
  
  	if (ctx->dataFH == NULL)
! 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
  					 fname, strerror(errno));
  }
  
*************** _EndBlob(ArchiveHandle *AH, TocEntry *te
*** 611,617 ****
  	/* 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");
  }
  
  /*
--- 611,617 ----
  	/* 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)
! 		exit_horribly(modulename, "could not write to blobs TOC file\n");
  }
  
  /*
*************** prependDirectory(ArchiveHandle *AH, cons
*** 667,673 ****
  	dname = ctx->directory;
  
  	if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH)
! 		die_horribly(AH, modulename, "path name too long: %s", dname);
  
  	strcpy(buf, dname);
  	strcat(buf, "/");
--- 667,673 ----
  	dname = ctx->directory;
  
  	if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH)
! 		exit_horribly(modulename, "path name too long: %s", dname);
  
  	strcpy(buf, dname);
  	strcat(buf, "/");
diff --git a/src/bin/pg_dump/pg_backup_files.c b/src/bin/pg_dump/pg_backup_files.c
index a7fd91d..d765838 100644
*** a/src/bin/pg_dump/pg_backup_files.c
--- b/src/bin/pg_dump/pg_backup_files.c
*************** InitArchiveFmt_Files(ArchiveHandle *AH)
*** 169,175 ****
  		ReadToc(AH);
  		/* Nothing else in the file... */
  		if (fclose(AH->FH) != 0)
! 			die_horribly(AH, modulename, "could not close TOC file: %s\n", strerror(errno));
  	}
  }
  
--- 169,175 ----
  		ReadToc(AH);
  		/* Nothing else in the file... */
  		if (fclose(AH->FH) != 0)
! 			exit_horribly(modulename, "could not close TOC file: %s\n", strerror(errno));
  	}
  }
  
*************** _StartData(ArchiveHandle *AH, TocEntry *
*** 259,266 ****
  #endif
  
  	if (tctx->FH == NULL)
! 		die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
! 					 tctx->filename, strerror(errno));
  }
  
  static size_t
--- 259,266 ----
  #endif
  
  	if (tctx->FH == NULL)
! 		exit_horribly(modulename, "could not open output file \"%s\": %s\n",
! 					  tctx->filename, strerror(errno));
  }
  
  static size_t
*************** _EndData(ArchiveHandle *AH, TocEntry *te
*** 280,286 ****
  
  	/* Close the file */
  	if (GZCLOSE(tctx->FH) != 0)
! 		die_horribly(AH, modulename, "could not close data file\n");
  
  	tctx->FH = NULL;
  }
--- 280,286 ----
  
  	/* Close the file */
  	if (GZCLOSE(tctx->FH) != 0)
! 		exit_horribly(modulename, "could not close data file\n");
  
  	tctx->FH = NULL;
  }
*************** _PrintFileData(ArchiveHandle *AH, char *
*** 304,310 ****
  #endif
  
  	if (AH->FH == NULL)
! 		die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
  					 filename, strerror(errno));
  
  	while ((cnt = GZREAD(buf, 1, 4095, AH->FH)) > 0)
--- 304,310 ----
  #endif
  
  	if (AH->FH == NULL)
! 		exit_horribly(modulename, "could not open input file \"%s\": %s\n",
  					 filename, strerror(errno));
  
  	while ((cnt = GZREAD(buf, 1, 4095, AH->FH)) > 0)
*************** _PrintFileData(ArchiveHandle *AH, char *
*** 314,320 ****
  	}
  
  	if (GZCLOSE(AH->FH) != 0)
! 		die_horribly(AH, modulename, "could not close data file after reading\n");
  }
  
  
--- 314,320 ----
  	}
  
  	if (GZCLOSE(AH->FH) != 0)
! 		exit_horribly(modulename, "could not close data file after reading\n");
  }
  
  
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 376,382 ****
  	ctx->blobToc = fopen("blobs.toc", PG_BINARY_R);
  
  	if (ctx->blobToc == NULL)
! 		die_horribly(AH, modulename, "could not open large object TOC for input: %s\n", strerror(errno));
  
  	_getBlobTocEntry(AH, &oid, fname);
  
--- 376,382 ----
  	ctx->blobToc = fopen("blobs.toc", PG_BINARY_R);
  
  	if (ctx->blobToc == NULL)
! 		exit_horribly(modulename, "could not open large object TOC for input: %s\n", strerror(errno));
  
  	_getBlobTocEntry(AH, &oid, fname);
  
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 389,395 ****
  	}
  
  	if (fclose(ctx->blobToc) != 0)
! 		die_horribly(AH, modulename, "could not close large object TOC file: %s\n", strerror(errno));
  
  	EndRestoreBlobs(AH);
  }
--- 389,395 ----
  	}
  
  	if (fclose(ctx->blobToc) != 0)
! 		exit_horribly(modulename, "could not close large object TOC file: %s\n", strerror(errno));
  
  	EndRestoreBlobs(AH);
  }
*************** _WriteByte(ArchiveHandle *AH, const int
*** 401,407 ****
  	lclContext *ctx = (lclContext *) AH->formatData;
  
  	if (fputc(i, AH->FH) == EOF)
! 		die_horribly(AH, modulename, "could not write byte\n");
  
  	ctx->filePos += 1;
  
--- 401,407 ----
  	lclContext *ctx = (lclContext *) AH->formatData;
  
  	if (fputc(i, AH->FH) == EOF)
! 		exit_horribly(modulename, "could not write byte\n");
  
  	ctx->filePos += 1;
  
*************** _ReadByte(ArchiveHandle *AH)
*** 416,422 ****
  
  	res = getc(AH->FH);
  	if (res == EOF)
! 		die_horribly(AH, modulename, "unexpected end of file\n");
  	ctx->filePos += 1;
  	return res;
  }
--- 416,422 ----
  
  	res = getc(AH->FH);
  	if (res == EOF)
! 		exit_horribly(modulename, "unexpected end of file\n");
  	ctx->filePos += 1;
  	return res;
  }
*************** _WriteBuf(ArchiveHandle *AH, const void
*** 429,435 ****
  
  	res = fwrite(buf, 1, len, AH->FH);
  	if (res != len)
! 		die_horribly(AH, modulename, "could not write to output file: %s\n", strerror(errno));
  
  	ctx->filePos += res;
  	return res;
--- 429,435 ----
  
  	res = fwrite(buf, 1, len, AH->FH);
  	if (res != len)
! 		exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno));
  
  	ctx->filePos += res;
  	return res;
*************** _CloseArchive(ArchiveHandle *AH)
*** 454,460 ****
  		WriteHead(AH);
  		WriteToc(AH);
  		if (fclose(AH->FH) != 0)
! 			die_horribly(AH, modulename, "could not close TOC file: %s\n", strerror(errno));
  		WriteDataChunks(AH);
  	}
  
--- 454,460 ----
  		WriteHead(AH);
  		WriteToc(AH);
  		if (fclose(AH->FH) != 0)
! 			exit_horribly(modulename, "could not close TOC file: %s\n", strerror(errno));
  		WriteDataChunks(AH);
  	}
  
*************** _StartBlobs(ArchiveHandle *AH, TocEntry
*** 486,492 ****
  	ctx->blobToc = fopen(fname, PG_BINARY_W);
  
  	if (ctx->blobToc == NULL)
! 		die_horribly(AH, modulename,
  		"could not open large object TOC for output: %s\n", strerror(errno));
  }
  
--- 486,492 ----
  	ctx->blobToc = fopen(fname, PG_BINARY_W);
  
  	if (ctx->blobToc == NULL)
! 		exit_horribly(modulename,
  		"could not open large object TOC for output: %s\n", strerror(errno));
  }
  
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 507,513 ****
  	char	   *sfx;
  
  	if (oid == 0)
! 		die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
  
  	if (AH->compression != 0)
  		sfx = ".gz";
--- 507,513 ----
  	char	   *sfx;
  
  	if (oid == 0)
! 		exit_horribly(modulename, "invalid OID for large object (%u)\n", oid);
  
  	if (AH->compression != 0)
  		sfx = ".gz";
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 526,532 ****
  #endif
  
  	if (tctx->FH == NULL)
! 		die_horribly(AH, modulename, "could not open large object file \"%s\" for input: %s\n",
  					 fname, strerror(errno));
  }
  
--- 526,532 ----
  #endif
  
  	if (tctx->FH == NULL)
! 		exit_horribly(modulename, "could not open large object file \"%s\" for input: %s\n",
  					 fname, strerror(errno));
  }
  
*************** _EndBlob(ArchiveHandle *AH, TocEntry *te
*** 541,547 ****
  	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
  
  	if (GZCLOSE(tctx->FH) != 0)
! 		die_horribly(AH, modulename, "could not close large object file\n");
  }
  
  /*
--- 541,547 ----
  	lclTocEntry *tctx = (lclTocEntry *) te->formatData;
  
  	if (GZCLOSE(tctx->FH) != 0)
! 		exit_horribly(modulename, "could not close large object file\n");
  }
  
  /*
*************** _EndBlobs(ArchiveHandle *AH, TocEntry *t
*** 558,562 ****
  	/* WriteInt(AH, 0); */
  
  	if (fclose(ctx->blobToc) != 0)
! 		die_horribly(AH, modulename, "could not close large object TOC file: %s\n", strerror(errno));
  }
--- 558,562 ----
  	/* WriteInt(AH, 0); */
  
  	if (fclose(ctx->blobToc) != 0)
! 		exit_horribly(modulename, "could not close large object TOC file: %s\n", strerror(errno));
  }
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index 201f0d9..ba1e461 100644
*** a/src/bin/pg_dump/pg_backup_null.c
--- b/src/bin/pg_dump/pg_backup_null.c
*************** InitArchiveFmt_Null(ArchiveHandle *AH)
*** 74,80 ****
  	 * Now prevent reading...
  	 */
  	if (AH->mode == archModeRead)
! 		die_horribly(AH, NULL, "this format cannot be read\n");
  }
  
  /*
--- 74,80 ----
  	 * Now prevent reading...
  	 */
  	if (AH->mode == archModeRead)
! 		exit_horribly(NULL, "this format cannot be read\n");
  }
  
  /*
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 149,155 ****
  	bool		old_blob_style = (AH->version < K_VERS_1_12);
  
  	if (oid == 0)
! 		die_horribly(AH, 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)
--- 149,155 ----
  	bool		old_blob_style = (AH->version < K_VERS_1_12);
  
  	if (oid == 0)
! 		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 4823ede..451c957 100644
*** a/src/bin/pg_dump/pg_backup_tar.c
--- b/src/bin/pg_dump/pg_backup_tar.c
*************** tarOpen(ArchiveHandle *AH, const char *f
*** 355,361 ****
  				 * 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);
  			}
  			else
  			{
--- 355,361 ----
  				 * Couldn't find the requested file. Future: do SEEK(0) and
  				 * retry.
  				 */
! 				exit_horribly(modulename, "could not find file \"%s\" in archive\n", filename);
  			}
  			else
  			{
*************** tarOpen(ArchiveHandle *AH, const char *f
*** 369,375 ****
  		if (AH->compression == 0)
  			tm->nFH = ctx->tarFH;
  		else
! 			die_horribly(AH, modulename, "compression is not supported by tar archive format\n");
  		/* tm->zFH = gzdopen(dup(fileno(ctx->tarFH)), "rb"); */
  #else
  		tm->nFH = ctx->tarFH;
--- 369,375 ----
  		if (AH->compression == 0)
  			tm->nFH = ctx->tarFH;
  		else
! 			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;
*************** tarOpen(ArchiveHandle *AH, const char *f
*** 411,417 ****
  #endif
  
  		if (tm->tmpFH == NULL)
! 			die_horribly(AH, modulename, "could not generate temporary file name: %s\n", strerror(errno));
  
  #ifdef HAVE_LIBZ
  
--- 411,417 ----
  #endif
  
  		if (tm->tmpFH == NULL)
! 			exit_horribly(modulename, "could not generate temporary file name: %s\n", strerror(errno));
  
  #ifdef HAVE_LIBZ
  
*************** tarOpen(ArchiveHandle *AH, const char *f
*** 420,426 ****
  			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");
  		}
  		else
  			tm->nFH = tm->tmpFH;
--- 420,426 ----
  			sprintf(fmode, "wb%d", AH->compression);
  			tm->zFH = gzdopen(dup(fileno(tm->tmpFH)), fmode);
  			if (tm->zFH == NULL)
! 				exit_horribly(modulename, "could not open temporary file\n");
  		}
  		else
  			tm->nFH = tm->tmpFH;
*************** tarClose(ArchiveHandle *AH, TAR_MEMBER *
*** 447,453 ****
  	 */
  	if (AH->compression != 0)
  		if (GZCLOSE(th->zFH) != 0)
! 			die_horribly(AH, modulename, "could not close tar member\n");
  
  	if (th->mode == 'w')
  		_tarAddFile(AH, th);	/* This will close the temp file */
--- 447,453 ----
  	 */
  	if (AH->compression != 0)
  		if (GZCLOSE(th->zFH) != 0)
! 			exit_horribly(modulename, "could not close tar member\n");
  
  	if (th->mode == 'w')
  		_tarAddFile(AH, th);	/* This will close the temp file */
*************** _tarReadRaw(ArchiveHandle *AH, void *buf
*** 547,553 ****
  				res = fread(&((char *) buf)[used], 1, len, th->nFH);
  		}
  		else
! 			die_horribly(AH, modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
  	}
  
  	ctx->tarFHpos += res + used;
--- 547,553 ----
  				res = fread(&((char *) buf)[used], 1, len, th->nFH);
  		}
  		else
! 			exit_horribly(modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n");
  	}
  
  	ctx->tarFHpos += res + used;
*************** tarWrite(const void *buf, size_t len, TA
*** 584,591 ****
  		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));
  
  	th->pos += res;
  	return res;
--- 584,591 ----
  		res = fwrite(buf, 1, len, th->nFH);
  
  	if (res != len)
! 		exit_horribly(modulename,
! 					  "could not write to output file: %s\n", strerror(errno));
  
  	th->pos += res;
  	return res;
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 672,679 ****
  		 * 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);
  
  		pos1 = 5;
  		for (pos1 = 5; pos1 < strlen(tmpCopy); pos1++)
--- 672,679 ----
  		 * we search the string for it in a paranoid sort of way.
  		 */
  		if (strncmp(tmpCopy, "copy ", 5) != 0)
! 			exit_horribly(modulename,
! 						  "invalid COPY statement -- could not find \"copy\" in string \"%s\"\n", tmpCopy);
  
  		pos1 = 5;
  		for (pos1 = 5; pos1 < strlen(tmpCopy); pos1++)
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 690,698 ****
  				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);
  
  		ahwrite(tmpCopy, 1, pos2, AH);	/* 'copy "table" [with oids]' */
  		ahprintf(AH, " from '$$PATH$$/%s' %s", tctx->filename, &tmpCopy[pos2 + 10]);
--- 690,698 ----
  				break;
  
  		if (pos2 >= strlen(tmpCopy))
! 			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]);
*************** _ReadByte(ArchiveHandle *AH)
*** 784,790 ****
  
  	res = tarRead(&c, 1, ctx->FH);
  	if (res != 1)
! 		die_horribly(AH, modulename, "unexpected end of file\n");
  	ctx->filePos += 1;
  	return c;
  }
--- 784,790 ----
  
  	res = tarRead(&c, 1, ctx->FH);
  	if (res != 1)
! 		exit_horribly(modulename, "unexpected end of file\n");
  	ctx->filePos += 1;
  	return c;
  }
*************** _CloseArchive(ArchiveHandle *AH)
*** 878,884 ****
  		for (i = 0; i < 512; i++)
  		{
  			if (fputc(0, ctx->tarFH) == EOF)
! 				die_horribly(AH, modulename,
  					   "could not write null block at end of tar archive\n");
  		}
  	}
--- 878,884 ----
  		for (i = 0; i < 512; i++)
  		{
  			if (fputc(0, ctx->tarFH) == EOF)
! 				exit_horribly(modulename,
  					   "could not write null block at end of tar archive\n");
  		}
  	}
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 934,940 ****
  	char	   *sfx;
  
  	if (oid == 0)
! 		die_horribly(AH, modulename, "invalid OID for large object (%u)\n", oid);
  
  	if (AH->compression != 0)
  		sfx = ".gz";
--- 934,940 ----
  	char	   *sfx;
  
  	if (oid == 0)
! 		exit_horribly(modulename, "invalid OID for large object (%u)\n", oid);
  
  	if (AH->compression != 0)
  		sfx = ".gz";
*************** _tarAddFile(ArchiveHandle *AH, TAR_MEMBE
*** 1077,1083 ****
  	 * 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");
  
  	_tarWriteHeader(th);
  
--- 1077,1083 ----
  	 * because pgoff_t can't exceed the compared maximum on their platform.
  	 */
  	if (th->fileLen > MAX_TAR_MEMBER_FILELEN)
! 		exit_horribly(modulename, "archive member too large for tar format\n");
  
  	_tarWriteHeader(th);
  
*************** _tarAddFile(ArchiveHandle *AH, TAR_MEMBE
*** 1085,1099 ****
  	{
  		res = fwrite(buf, 1, cnt, th->tarFH);
  		if (res != cnt)
! 			die_horribly(AH, 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));
  
  	if (len != th->fileLen)
  	{
--- 1085,1099 ----
  	{
  		res = fwrite(buf, 1, cnt, th->tarFH);
  		if (res != cnt)
! 			exit_horribly(modulename,
! 						  "could not write to output file: %s\n",
! 						  strerror(errno));
  		len += res;
  	}
  
  	if (fclose(tmp) != 0)		/* This *should* delete it... */
! 		exit_horribly(modulename, "could not close temporary file: %s\n",
! 					  strerror(errno));
  
  	if (len != th->fileLen)
  	{
*************** _tarAddFile(ArchiveHandle *AH, TAR_MEMBE
*** 1102,1116 ****
  
  		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);
  	}
  
  	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");
  	}
  
  	ctx->tarFHpos += len + pad;
--- 1102,1116 ----
  
  		snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) len);
  		snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) th->fileLen);
! 		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)
! 			exit_horribly(modulename, "could not output padding at end of tar member\n");
  	}
  
  	ctx->tarFHpos += len + pad;
*************** _tarPositionTo(ArchiveHandle *AH, const
*** 1159,1165 ****
  	if (!_tarGetHeader(AH, th))
  	{
  		if (filename)
! 			die_horribly(AH, modulename, "could not find header for file \"%s\" in tar archive\n", filename);
  		else
  		{
  			/*
--- 1159,1165 ----
  	if (!_tarGetHeader(AH, th))
  	{
  		if (filename)
! 			exit_horribly(modulename, "could not find header for file \"%s\" in tar archive\n", filename);
  		else
  		{
  			/*
*************** _tarPositionTo(ArchiveHandle *AH, const
*** 1177,1185 ****
  
  		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);
  
  		/* Header doesn't match, so read to next header */
  		len = ((th->fileLen + 511) & ~511);		/* Padded length */
--- 1177,1185 ----
  
  		id = atoi(th->targetFile);
  		if ((TocIDRequired(AH, id, AH->ropt) & REQ_DATA) != 0)
! 			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 */
*************** _tarPositionTo(ArchiveHandle *AH, const
*** 1189,1195 ****
  			_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);
  	}
  
  	ctx->tarNextMember = ctx->tarFHpos + ((th->fileLen + 511) & ~511);
--- 1189,1195 ----
  			_tarReadRaw(AH, &header[0], 512, NULL, ctx->tarFH);
  
  		if (!_tarGetHeader(AH, th))
! 			exit_horribly(modulename, "could not find header for file \"%s\" in tar archive\n", filename);
  	}
  
  	ctx->tarNextMember = ctx->tarFHpos + ((th->fileLen + 511) & ~511);
*************** _tarGetHeader(ArchiveHandle *AH, TAR_MEM
*** 1222,1228 ****
  
  			snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ftello(ctx->tarFH));
  			snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ftello(ctx->tarFHpos));
! 			die_horribly(AH, modulename,
  			  "mismatch in actual vs. predicted file position (%s vs. %s)\n",
  						 buf1, buf2);
  		}
--- 1222,1228 ----
  
  			snprintf(buf1, sizeof(buf1), INT64_FORMAT, (int64) ftello(ctx->tarFH));
  			snprintf(buf2, sizeof(buf2), INT64_FORMAT, (int64) ftello(ctx->tarFHpos));
! 			exit_horribly(modulename,
  			  "mismatch in actual vs. predicted file position (%s vs. %s)\n",
  						 buf1, buf2);
  		}
*************** _tarGetHeader(ArchiveHandle *AH, TAR_MEM
*** 1237,1247 ****
  			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);
  
  		/* Calc checksum */
  		chk = _tarChecksum(h);
--- 1237,1247 ----
  			return 0;
  
  		if (len != 512)
! 			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);
*************** _tarGetHeader(ArchiveHandle *AH, TAR_MEM
*** 1285,1294 ****
  		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);
  	}
  
  	th->targetFile = pg_strdup(tag);
--- 1285,1294 ----
  		char		buf[100];
  
  		snprintf(buf, sizeof(buf), INT64_FORMAT, (int64) ftello(ctx->tarFH));
! 		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);
*************** _tarWriteHeader(TAR_MEMBER *th)
*** 1379,1383 ****
  	}
  
  	if (fwrite(h, 1, 512, th->tarFH) != 512)
! 		die_horribly(th->AH, modulename, "could not write to output file: %s\n", strerror(errno));
  }
--- 1379,1383 ----
  	}
  
  	if (fwrite(h, 1, 512, th->tarFH) != 512)
! 		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 2b0a5ff..de1955f 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** static int	serializable_deferrable = 0;
*** 144,150 ****
  
  
  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);
--- 144,149 ----
*************** main(int argc, char **argv)
*** 575,581 ****
  
  	/* Open the output file */
  	fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode);
! 	on_exit_nicely(pgdump_cleanup_at_exit, fout);
  
  	if (fout == NULL)
  		exit_horribly(NULL, "could not open output file \"%s\" for writing\n", filename);
--- 574,580 ----
  
  	/* Open the output file */
  	fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode);
! 	on_exit_nicely(archive_close_connection, fout);
  
  	if (fout == NULL)
  		exit_horribly(NULL, "could not open output file \"%s\" for writing\n", filename);
*************** help(const char *progname)
*** 837,850 ****
  }
  
  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)
  {
  	PGconn	   *conn = GetConnection(AH);
--- 836,841 ----
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index b5f4c62..370409b 100644
*** a/src/bin/pg_dump/pg_restore.c
--- b/src/bin/pg_dump/pg_restore.c
*************** main(int argc, char **argv)
*** 384,389 ****
--- 384,396 ----
  
  	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_nicely(archive_close_connection, AH);
+ 
  	/* Let the archiver know how noisy to be */
  	AH->verbose = opts->verbose;