*** a/src/bin/pg_dump/Makefile
--- b/src/bin/pg_dump/Makefile
***************
*** 19,25 **** include $(top_builddir)/src/Makefile.global
  override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
  
  OBJS=	pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
! 	pg_backup_null.o pg_backup_tar.o parallel.o \
  	pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
  
  KEYWRDOBJS = keywords.o kwlookup.o
--- 19,25 ----
  override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
  
  OBJS=	pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
! 	pg_backup_null.o pg_backup_tar.o parallel.o misc.o \
  	pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
  
  KEYWRDOBJS = keywords.o kwlookup.o
*** a/src/bin/pg_dump/common.c
--- b/src/bin/pg_dump/common.c
***************
*** 14,19 ****
--- 14,20 ----
   *-------------------------------------------------------------------------
   */
  #include "pg_backup_archiver.h"
+ #include "misc.h"
  
  #include <ctype.h>
  
*** a/src/bin/pg_dump/compress_io.c
--- b/src/bin/pg_dump/compress_io.c
***************
*** 53,59 ****
   */
  
  #include "compress_io.h"
! #include "dumputils.h"
  #include "parallel.h"
  
  /*----------------------
--- 53,59 ----
   */
  
  #include "compress_io.h"
! #include "misc.h"
  #include "parallel.h"
  
  /*----------------------
*** a/src/bin/pg_dump/dumputils.c
--- b/src/bin/pg_dump/dumputils.c
***************
*** 25,45 ****
  extern const ScanKeyword FEScanKeywords[];
  extern const int NumFEScanKeywords;
  
- /* Globals exported by this file */
- int			quote_all_identifiers = 0;
- const char *progname = NULL;
- 
- #define MAX_ON_EXIT_NICELY				20
- 
- static struct
- {
- 	on_exit_nicely_callback function;
- 	void	   *arg;
- }	on_exit_nicely_list[MAX_ON_EXIT_NICELY];
- 
- static int	on_exit_nicely_index;
- void		(*on_exit_msg_func) (const char *modulename, const char *fmt, va_list ap) = vwrite_msg;
- 
  #define supports_grant_options(version) ((version) >= 70400)
  
  static bool parseAclItem(const char *item, const char *type,
--- 25,30 ----
***************
*** 49,116 **** static bool parseAclItem(const char *item, const char *type,
  static char *copyAclUserName(PQExpBuffer output, char *input);
  static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
  	   const char *subname);
! static PQExpBuffer getThreadLocalPQExpBuffer(void);
! 
! #ifdef WIN32
! static void shutdown_parallel_dump_utils(int code, void *unused);
! static bool parallel_init_done = false;
! static DWORD tls_index;
! static DWORD mainThreadId;
  
! static void
! shutdown_parallel_dump_utils(int code, void *unused)
! {
! 	/* Call the cleanup function only from the main thread */
! 	if (mainThreadId == GetCurrentThreadId())
! 		WSACleanup();
! }
! #endif
! 
! void
! init_parallel_dump_utils(void)
! {
! #ifdef WIN32
! 	if (!parallel_init_done)
! 	{
! 		WSADATA		wsaData;
! 		int			err;
! 
! 		tls_index = TlsAlloc();
! 		mainThreadId = GetCurrentThreadId();
! 		err = WSAStartup(MAKEWORD(2, 2), &wsaData);
! 		if (err != 0)
! 		{
! 			fprintf(stderr, _("WSAStartup failed: %d\n"), err);
! 			exit_nicely(1);
! 		}
! 		on_exit_nicely(shutdown_parallel_dump_utils, NULL);
! 		parallel_init_done = true;
! 	}
! #endif
! }
  
  /*
!  * Non-reentrant but reduces memory leakage. (On Windows the memory leakage
!  * will be one buffer per thread, which is at least better than one per call).
   */
  static PQExpBuffer
! getThreadLocalPQExpBuffer(void)
  {
! 	/*
! 	 * The Tls code goes awry if we use a static var, so we provide for both
! 	 * static and auto, and omit any use of the static var when using Tls.
! 	 */
! 	static PQExpBuffer s_id_return = NULL;
! 	PQExpBuffer id_return;
! 
! #ifdef WIN32
! 	if (parallel_init_done)
! 		id_return = (PQExpBuffer) TlsGetValue(tls_index);		/* 0 when not set */
! 	else
! 		id_return = s_id_return;
! #else
! 	id_return = s_id_return;
! #endif
  
  	if (id_return)				/* first time through? */
  	{
--- 34,57 ----
  static char *copyAclUserName(PQExpBuffer output, char *input);
  static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
  	   const char *subname);
! static PQExpBuffer defaultGetLocalPQExpBuffer(void);
  
! /* Globals exported by this file */
! int			quote_all_identifiers = 0;
! PQExpBuffer (*getLocalPQExpBuffer) (void) = defaultGetLocalPQExpBuffer;
  
  /*
!  * Returns a temporary PQExpBuffer, valid until the next call to the function.
!  * This is used by fmtId and fmtQualifiedId.
!  *
!  * Non-reentrant and non-thread-safe but reduces memory leakage. You can
!  * replace this with a custom version by setting the getLocalPQExpBuffer
!  * function pointer.
   */
  static PQExpBuffer
! defaultGetLocalPQExpBuffer(void)
  {
! 	static PQExpBuffer id_return = NULL;
  
  	if (id_return)				/* first time through? */
  	{
***************
*** 121,135 **** getThreadLocalPQExpBuffer(void)
  	{
  		/* new buffer */
  		id_return = createPQExpBuffer();
- #ifdef WIN32
- 		if (parallel_init_done)
- 			TlsSetValue(tls_index, id_return);
- 		else
- 			s_id_return = id_return;
- #else
- 		s_id_return = id_return;
- #endif
- 
  	}
  
  	return id_return;
--- 62,67 ----
***************
*** 144,150 **** getThreadLocalPQExpBuffer(void)
  const char *
  fmtId(const char *rawid)
  {
! 	PQExpBuffer id_return = getThreadLocalPQExpBuffer();
  
  	const char *cp;
  	bool		need_quotes = false;
--- 76,82 ----
  const char *
  fmtId(const char *rawid)
  {
! 	PQExpBuffer id_return = getLocalPQExpBuffer();
  
  	const char *cp;
  	bool		need_quotes = false;
***************
*** 238,244 **** fmtQualifiedId(int remoteVersion, const char *schema, const char *id)
  	}
  	appendPQExpBuffer(lcl_pqexp, "%s", fmtId(id));
  
! 	id_return = getThreadLocalPQExpBuffer();
  
  	appendPQExpBuffer(id_return, "%s", lcl_pqexp->data);
  	destroyPQExpBuffer(lcl_pqexp);
--- 170,176 ----
  	}
  	appendPQExpBuffer(lcl_pqexp, "%s", fmtId(id));
  
! 	id_return = getLocalPQExpBuffer();
  
  	appendPQExpBuffer(id_return, "%s", lcl_pqexp->data);
  	destroyPQExpBuffer(lcl_pqexp);
***************
*** 1278,1395 **** emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
  }
  
  
- /*
-  * Parse a --section=foo command line argument.
-  *
-  * Set or update the bitmask in *dumpSections according to arg.
-  * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
-  * pg_restore so they can know if this has even been called.
-  */
- void
- set_dump_section(const char *arg, int *dumpSections)
- {
- 	/* if this is the first call, clear all the bits */
- 	if (*dumpSections == DUMP_UNSECTIONED)
- 		*dumpSections = 0;
- 
- 	if (strcmp(arg, "pre-data") == 0)
- 		*dumpSections |= DUMP_PRE_DATA;
- 	else if (strcmp(arg, "data") == 0)
- 		*dumpSections |= DUMP_DATA;
- 	else if (strcmp(arg, "post-data") == 0)
- 		*dumpSections |= DUMP_POST_DATA;
- 	else
- 	{
- 		fprintf(stderr, _("%s: unrecognized section name: \"%s\"\n"),
- 				progname, arg);
- 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
- 				progname);
- 		exit_nicely(1);
- 	}
- }
- 
- 
- /*
-  * Write a printf-style message to stderr.
-  *
-  * The program name is prepended, if "progname" has been set.
-  * Also, if modulename isn't NULL, that's included too.
-  * Note that we'll try to translate the modulename and the fmt string.
-  */
- void
- write_msg(const char *modulename, const char *fmt,...)
- {
- 	va_list		ap;
- 
- 	va_start(ap, fmt);
- 	vwrite_msg(modulename, fmt, ap);
- 	va_end(ap);
- }
- 
- /*
-  * As write_msg, but pass a va_list not variable arguments.
-  */
- void
- vwrite_msg(const char *modulename, const char *fmt, va_list ap)
- {
- 	if (progname)
- 	{
- 		if (modulename)
- 			fprintf(stderr, "%s: [%s] ", progname, _(modulename));
- 		else
- 			fprintf(stderr, "%s: ", progname);
- 	}
- 	vfprintf(stderr, _(fmt), ap);
- }
- 
- 
- /*
-  * Fail and die, with a message to stderr.	Parameters as for write_msg.
-  */
- void
- exit_horribly(const char *modulename, const char *fmt,...)
- {
- 	va_list		ap;
- 
- 	va_start(ap, fmt);
- 	on_exit_msg_func(modulename, fmt, ap);
- 	va_end(ap);
- 
- 	exit_nicely(1);
- }
- 
- /* Register a callback to be run when exit_nicely is invoked. */
- void
- on_exit_nicely(on_exit_nicely_callback function, void *arg)
- {
- 	if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
- 		exit_horribly(NULL, "out of on_exit_nicely slots\n");
- 	on_exit_nicely_list[on_exit_nicely_index].function = function;
- 	on_exit_nicely_list[on_exit_nicely_index].arg = arg;
- 	on_exit_nicely_index++;
- }
- 
- /*
-  * Run accumulated on_exit_nicely callbacks in reverse order and then exit
-  * quietly.  This needs to be thread-safe.
-  */
- void
- exit_nicely(int code)
- {
- 	int			i;
- 
- 	for (i = on_exit_nicely_index - 1; i >= 0; i--)
- 		(*on_exit_nicely_list[i].function) (code,
- 											on_exit_nicely_list[i].arg);
- 
- #ifdef WIN32
- 	if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
- 		ExitThread(code);
- #endif
- 
- 	exit(code);
- }
- 
  void
  simple_string_list_append(SimpleStringList *list, const char *val)
  {
--- 1210,1215 ----
*** a/src/bin/pg_dump/dumputils.h
--- b/src/bin/pg_dump/dumputils.h
***************
*** 19,32 ****
  #include "libpq-fe.h"
  #include "pqexpbuffer.h"
  
- typedef enum					/* bits returned by set_dump_section */
- {
- 	DUMP_PRE_DATA = 0x01,
- 	DUMP_DATA = 0x02,
- 	DUMP_POST_DATA = 0x04,
- 	DUMP_UNSECTIONED = 0xff
- } DumpSections;
- 
  typedef struct SimpleStringListCell
  {
  	struct SimpleStringListCell *next;
--- 19,24 ----
***************
*** 40,53 **** typedef struct SimpleStringList
  } SimpleStringList;
  
  
- typedef void (*on_exit_nicely_callback) (int code, void *arg);
- 
  extern int	quote_all_identifiers;
! extern const char *progname;
! extern void (*on_exit_msg_func) (const char *modulename, const char *fmt, va_list ap)
! __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
  
- extern void init_parallel_dump_utils(void);
  extern const char *fmtId(const char *identifier);
  extern const char *fmtQualifiedId(int remoteVersion,
  			   const char *schema, const char *id);
--- 32,40 ----
  } SimpleStringList;
  
  
  extern int	quote_all_identifiers;
! extern PQExpBuffer (*getLocalPQExpBuffer) (void);
  
  extern const char *fmtId(const char *identifier);
  extern const char *fmtQualifiedId(int remoteVersion,
  			   const char *schema, const char *id);
***************
*** 79,95 **** extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name,
  extern void emitShSecLabels(PGconn *conn, PGresult *res,
  				PQExpBuffer buffer, const char *target, const char *objname);
  extern void set_dump_section(const char *arg, int *dumpSections);
- extern void
- write_msg(const char *modulename, const char *fmt,...)
- __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
- extern void
- vwrite_msg(const char *modulename, const char *fmt, va_list ap)
- __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
- extern void
- exit_horribly(const char *modulename, const char *fmt,...)
- __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3), noreturn));
- extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
- extern void exit_nicely(int code) __attribute__((noreturn));
  
  extern void simple_string_list_append(SimpleStringList *list, const char *val);
  extern bool simple_string_list_member(SimpleStringList *list, const char *val);
--- 66,71 ----
*** /dev/null
--- b/src/bin/pg_dump/misc.c
***************
*** 0 ****
--- 1,126 ----
+ /*-------------------------------------------------------------------------
+  *
+  * misc.c
+  *	Utility routines shared by pg_dump and pg_restore
+  *
+  *
+  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * src/bin/pg_dump/misc.c
+  *
+  *-------------------------------------------------------------------------
+  */
+ #include "postgres_fe.h"
+ 
+ #include "misc.h"
+ #include "parallel.h"
+ 
+ /* Globals exported by this file */
+ const char *progname = NULL;
+ 
+ #define MAX_ON_EXIT_NICELY				20
+ 
+ static struct
+ {
+ 	on_exit_nicely_callback function;
+ 	void	   *arg;
+ }	on_exit_nicely_list[MAX_ON_EXIT_NICELY];
+ 
+ static int	on_exit_nicely_index;
+ 
+ /*
+  * Parse a --section=foo command line argument.
+  *
+  * Set or update the bitmask in *dumpSections according to arg.
+  * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
+  * pg_restore so they can know if this has even been called.
+  */
+ void
+ set_dump_section(const char *arg, int *dumpSections)
+ {
+ 	/* if this is the first call, clear all the bits */
+ 	if (*dumpSections == DUMP_UNSECTIONED)
+ 		*dumpSections = 0;
+ 
+ 	if (strcmp(arg, "pre-data") == 0)
+ 		*dumpSections |= DUMP_PRE_DATA;
+ 	else if (strcmp(arg, "data") == 0)
+ 		*dumpSections |= DUMP_DATA;
+ 	else if (strcmp(arg, "post-data") == 0)
+ 		*dumpSections |= DUMP_POST_DATA;
+ 	else
+ 	{
+ 		fprintf(stderr, _("%s: unrecognized section name: \"%s\"\n"),
+ 				progname, arg);
+ 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+ 				progname);
+ 		exit_nicely(1);
+ 	}
+ }
+ 
+ 
+ /*
+  * Write a printf-style message to stderr.
+  *
+  * The program name is prepended, if "progname" has been set.
+  * Also, if modulename isn't NULL, that's included too.
+  * Note that we'll try to translate the modulename and the fmt string.
+  */
+ void
+ write_msg(const char *modulename, const char *fmt,...)
+ {
+ 	va_list		ap;
+ 
+ 	va_start(ap, fmt);
+ 	vwrite_msg(modulename, fmt, ap);
+ 	va_end(ap);
+ }
+ 
+ /*
+  * As write_msg, but pass a va_list not variable arguments.
+  */
+ void
+ vwrite_msg(const char *modulename, const char *fmt, va_list ap)
+ {
+ 	if (progname)
+ 	{
+ 		if (modulename)
+ 			fprintf(stderr, "%s: [%s] ", progname, _(modulename));
+ 		else
+ 			fprintf(stderr, "%s: ", progname);
+ 	}
+ 	vfprintf(stderr, _(fmt), ap);
+ }
+ 
+ /* Register a callback to be run when exit_nicely is invoked. */
+ void
+ on_exit_nicely(on_exit_nicely_callback function, void *arg)
+ {
+ 	if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
+ 		exit_horribly(NULL, "out of on_exit_nicely slots\n");
+ 	on_exit_nicely_list[on_exit_nicely_index].function = function;
+ 	on_exit_nicely_list[on_exit_nicely_index].arg = arg;
+ 	on_exit_nicely_index++;
+ }
+ 
+ /*
+  * Run accumulated on_exit_nicely callbacks in reverse order and then exit
+  * quietly.  This needs to be thread-safe.
+  */
+ void
+ exit_nicely(int code)
+ {
+ 	int			i;
+ 
+ 	for (i = on_exit_nicely_index - 1; i >= 0; i--)
+ 		(*on_exit_nicely_list[i].function) (code,
+ 											on_exit_nicely_list[i].arg);
+ 
+ #ifdef WIN32
+ 	if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
+ 		ExitThread(code);
+ #endif
+ 
+ 	exit(code);
+ }
*** /dev/null
--- b/src/bin/pg_dump/misc.h
***************
*** 0 ****
--- 1,47 ----
+ /*-------------------------------------------------------------------------
+  *
+  * misc.h
+  *	Utility routines shared by pg_dump and pg_restore.
+  *
+  *
+  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * src/bin/pg_dump/misc.h
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #ifndef PG_DUMP_MISC_H
+ #define PG_DUMP_MISC_H
+ 
+ #include "libpq-fe.h"
+ #include "pqexpbuffer.h"
+ 
+ typedef enum					/* bits returned by set_dump_section */
+ {
+ 	DUMP_PRE_DATA = 0x01,
+ 	DUMP_DATA = 0x02,
+ 	DUMP_POST_DATA = 0x04,
+ 	DUMP_UNSECTIONED = 0xff
+ } DumpSections;
+ 
+ typedef void (*on_exit_nicely_callback) (int code, void *arg);
+ 
+ extern const char *progname;
+ extern void (*on_exit_msg_func) (const char *modulename, const char *fmt, va_list ap)
+ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
+ 
+ extern void set_dump_section(const char *arg, int *dumpSections);
+ extern void
+ write_msg(const char *modulename, const char *fmt,...)
+ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
+ extern void
+ vwrite_msg(const char *modulename, const char *fmt, va_list ap)
+ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
+ extern void on_exit_nicely(on_exit_nicely_callback function, void *arg);
+ extern void exit_nicely(int code) __attribute__((noreturn));
+ 
+ extern void init_parallel_dump_utils(void);
+ 
+ #endif   /* PG_DUMP_MISC_H */
*** a/src/bin/pg_dump/parallel.c
--- b/src/bin/pg_dump/parallel.c
***************
*** 16,24 ****
   *-------------------------------------------------------------------------
   */
  
! #include "pg_backup_db.h"
  
! #include "dumputils.h"
  #include "parallel.h"
  
  #ifndef WIN32
--- 16,24 ----
   *-------------------------------------------------------------------------
   */
  
! #include "postgres_fe.h"
  
! #include "misc.h"
  #include "parallel.h"
  
  #ifndef WIN32
***************
*** 78,87 **** static const char *modulename = gettext_noop("parallel archiver");
  
  static ParallelSlot *GetMyPSlot(ParallelState *pstate);
  static void
- parallel_exit_msg_func(const char *modulename,
- 					   const char *fmt, va_list ap)
- __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
- static void
  parallel_msg_master(ParallelSlot *slot, const char *modulename,
  					const char *fmt, va_list ap)
  __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
--- 78,83 ----
***************
*** 112,117 **** static char *readMessageFromPipe(int fd);
--- 108,120 ----
  #define messageEquals(msg, pattern) \
  	(strcmp(msg, pattern) == 0)
  
+ #ifdef WIN32
+ static void shutdown_parallel_dump_utils(int code, void *unused);
+ bool parallel_init_done = false;
+ static DWORD tls_index;
+ DWORD mainThreadId;
+ #endif
+ 
  static ParallelSlot *
  GetMyPSlot(ParallelState *pstate)
  {
***************
*** 128,157 **** GetMyPSlot(ParallelState *pstate)
  	return NULL;
  }
  
  /*
!  * This is the function that will be called from exit_horribly() to print the
!  * error message. If the worker process does exit_horribly(), we forward its
   * last words to the master process. The master process then does
   * exit_horribly() with this error message itself and prints it normally.
   * After printing the message, exit_horribly() on the master will shut down
   * the remaining worker processes.
   */
! static void
! parallel_exit_msg_func(const char *modulename, const char *fmt, va_list ap)
  {
  	ParallelState *pstate = shutdown_info.pstate;
  	ParallelSlot *slot;
  
! 	Assert(pstate);
  
! 	slot = GetMyPSlot(pstate);
! 
! 	if (!slot)
! 		/* We're the parent, just write the message out */
  		vwrite_msg(modulename, fmt, ap);
  	else
! 		/* If we're a worker process, send the msg to the master process */
! 		parallel_msg_master(slot, modulename, fmt, ap);
  }
  
  /* Sends the error message from the worker to the master process */
--- 131,176 ----
  	return NULL;
  }
  
+ 
  /*
!  * Fail and die, with a message to stderr.	Parameters as for write_msg.
!  *
!  * This is defined in parallel.c, because in parallel mode, things are more
!  * complicated. If the worker process does exit_horribly(), we forward its
   * last words to the master process. The master process then does
   * exit_horribly() with this error message itself and prints it normally.
   * After printing the message, exit_horribly() on the master will shut down
   * the remaining worker processes.
   */
! void
! exit_horribly(const char *modulename, const char *fmt,...)
  {
+ 	va_list		ap;
  	ParallelState *pstate = shutdown_info.pstate;
  	ParallelSlot *slot;
  
! 	va_start(ap, fmt);
  
! 	if (pstate == NULL)
! 	{
! 		/* Not in parallel mode, just write to stderr */
  		vwrite_msg(modulename, fmt, ap);
+ 	}
  	else
! 	{
! 		slot = GetMyPSlot(pstate);
! 
! 		if (!slot)
! 			/* We're the parent, just write the message out */
! 			vwrite_msg(modulename, fmt, ap);
! 		else
! 			/* If we're a worker process, send the msg to the master process */
! 			parallel_msg_master(slot, modulename, fmt, ap);
! 	}
! 
! 	va_end(ap);
! 
! 	exit_nicely(1);
  }
  
  /* Sends the error message from the worker to the master process */
***************
*** 172,177 **** parallel_msg_master(ParallelSlot *slot, const char *modulename,
--- 191,277 ----
  	sendMessageToMaster(pipefd, buf);
  }
  
+ #ifdef WIN32
+ static void
+ shutdown_parallel_dump_utils(int code, void *unused)
+ {
+ 	/* Call the cleanup function only from the main thread */
+ 	if (mainThreadId == GetCurrentThreadId())
+ 		WSACleanup();
+ }
+ #endif
+ 
+ void
+ init_parallel_dump_utils(void)
+ {
+ #ifdef WIN32
+ 	if (!parallel_init_done)
+ 	{
+ 		WSADATA		wsaData;
+ 		int			err;
+ 
+ 		tls_index = TlsAlloc();
+ 		mainThreadId = GetCurrentThreadId();
+ 		err = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ 		if (err != 0)
+ 		{
+ 			fprintf(stderr, _("WSAStartup failed: %d\n"), err);
+ 			exit_nicely(1);
+ 		}
+ 		on_exit_nicely(shutdown_parallel_dump_utils, NULL);
+ 		parallel_init_done = true;
+ 	}
+ #endif
+ }
+ 
+ /*
+  * A thread-local version of getLocalPQExpBuffer().
+  *
+  * Non-reentrant but reduces memory leakage. (On Windows the memory leakage
+  * will be one buffer per thread, which is at least better than one per call).
+  */
+ static PQExpBuffer
+ getThreadLocalPQExpBuffer(void)
+ {
+ 	/*
+ 	 * The Tls code goes awry if we use a static var, so we provide for both
+ 	 * static and auto, and omit any use of the static var when using Tls.
+ 	 */
+ 	static PQExpBuffer s_id_return = NULL;
+ 	PQExpBuffer id_return;
+ 
+ #ifdef WIN32
+ 	if (parallel_init_done)
+ 		id_return = (PQExpBuffer) TlsGetValue(tls_index);		/* 0 when not set */
+ 	else
+ 		id_return = s_id_return;
+ #else
+ 	id_return = s_id_return;
+ #endif
+ 
+ 	if (id_return)				/* first time through? */
+ 	{
+ 		/* same buffer, just wipe contents */
+ 		resetPQExpBuffer(id_return);
+ 	}
+ 	else
+ 	{
+ 		/* new buffer */
+ 		id_return = createPQExpBuffer();
+ #ifdef WIN32
+ 		if (parallel_init_done)
+ 			TlsSetValue(tls_index, id_return);
+ 		else
+ 			s_id_return = id_return;
+ #else
+ 		s_id_return = id_return;
+ #endif
+ 
+ 	}
+ 
+ 	return id_return;
+ }
+ 
  /*
   * pg_dump and pg_restore register the Archive pointer for the exit handler
   * (called from exit_horribly). This function mainly exists so that we can
***************
*** 408,414 **** ParallelBackupStart(ArchiveHandle *AH, RestoreOptions *ropt)
  	 * set and falls back to AHX otherwise.
  	 */
  	shutdown_info.pstate = pstate;
! 	on_exit_msg_func = parallel_exit_msg_func;
  
  #ifdef WIN32
  	tMasterThreadId = GetCurrentThreadId();
--- 508,514 ----
  	 * set and falls back to AHX otherwise.
  	 */
  	shutdown_info.pstate = pstate;
! 	getLocalPQExpBuffer = getThreadLocalPQExpBuffer;
  
  #ifdef WIN32
  	tMasterThreadId = GetCurrentThreadId();
*** a/src/bin/pg_dump/parallel.h
--- b/src/bin/pg_dump/parallel.h
***************
*** 16,21 ****
--- 16,24 ----
   *-------------------------------------------------------------------------
   */
  
+ #ifndef PG_DUMP_PARALLEL_H
+ #define PG_DUMP_PARALLEL_H
+ 
  #include "pg_backup_db.h"
  
  struct _archiveHandle;
***************
*** 62,67 **** typedef struct ParallelState
--- 65,75 ----
  	ParallelSlot *parallelSlot;
  } ParallelState;
  
+ #ifdef WIN32
+ extern bool parallel_init_done;
+ extern DWORD mainThreadId;
+ #endif
+ 
  extern int	GetIdleWorker(ParallelState *pstate);
  extern bool IsEveryWorkerIdle(ParallelState *pstate);
  extern void ListenToWorkers(struct _archiveHandle * AH, ParallelState *pstate, bool do_wait);
***************
*** 77,79 **** extern void DispatchJobForTocEntry(struct _archiveHandle * AH,
--- 85,93 ----
  extern void ParallelBackupEnd(struct _archiveHandle * AH, ParallelState *pstate);
  
  extern void checkAborting(struct _archiveHandle * AH);
+ 
+ extern void
+ exit_horribly(const char *modulename, const char *fmt,...)
+ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3), noreturn));
+ 
+ #endif   /* PG_DUMP_PARALLEL_H */
*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
***************
*** 21,27 ****
   */
  
  #include "pg_backup_db.h"
! #include "dumputils.h"
  #include "parallel.h"
  
  #include <ctype.h>
--- 21,27 ----
   */
  
  #include "pg_backup_db.h"
! #include "misc.h"
  #include "parallel.h"
  
  #include <ctype.h>
*** a/src/bin/pg_dump/pg_backup_custom.c
--- b/src/bin/pg_dump/pg_backup_custom.c
***************
*** 25,31 ****
   */
  
  #include "compress_io.h"
! #include "dumputils.h"
  #include "parallel.h"
  
  /*--------
--- 25,31 ----
   */
  
  #include "compress_io.h"
! #include "misc.h"
  #include "parallel.h"
  
  /*--------
*** a/src/bin/pg_dump/pg_backup_db.c
--- b/src/bin/pg_dump/pg_backup_db.c
***************
*** 12,17 ****
--- 12,19 ----
  
  #include "pg_backup_db.h"
  #include "dumputils.h"
+ #include "misc.h"
+ #include "parallel.h"
  
  #include <unistd.h>
  #include <ctype.h>
*** a/src/bin/pg_dump/pg_backup_directory.c
--- b/src/bin/pg_dump/pg_backup_directory.c
***************
*** 34,40 ****
   */
  
  #include "compress_io.h"
! #include "dumputils.h"
  #include "parallel.h"
  
  #include <dirent.h>
--- 34,40 ----
   */
  
  #include "compress_io.h"
! #include "misc.h"
  #include "parallel.h"
  
  #include <dirent.h>
*** a/src/bin/pg_dump/pg_backup_null.c
--- b/src/bin/pg_dump/pg_backup_null.c
***************
*** 23,29 ****
   */
  
  #include "pg_backup_archiver.h"
! #include "dumputils.h"
  
  #include <unistd.h>				/* for dup */
  
--- 23,30 ----
   */
  
  #include "pg_backup_archiver.h"
! #include "misc.h"
! #include "parallel.h"
  
  #include <unistd.h>				/* for dup */
  
*** a/src/bin/pg_dump/pg_backup_tar.c
--- b/src/bin/pg_dump/pg_backup_tar.c
***************
*** 31,37 ****
  #include "pg_backup.h"
  #include "pg_backup_archiver.h"
  #include "pg_backup_tar.h"
! #include "dumputils.h"
  #include "pgtar.h"
  
  #include <sys/stat.h>
--- 31,38 ----
  #include "pg_backup.h"
  #include "pg_backup_archiver.h"
  #include "pg_backup_tar.h"
! #include "misc.h"
! #include "parallel.h"
  #include "pgtar.h"
  
  #include <sys/stat.h>
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 60,65 ****
--- 60,67 ----
  #include "pg_backup_archiver.h"
  #include "pg_backup_db.h"
  #include "dumputils.h"
+ #include "misc.h"
+ #include "parallel.h"
  
  extern char *optarg;
  extern int	optind,
*** a/src/bin/pg_dump/pg_dump_sort.c
--- b/src/bin/pg_dump/pg_dump_sort.c
***************
*** 14,20 ****
   *-------------------------------------------------------------------------
   */
  #include "pg_backup_archiver.h"
! #include "dumputils.h"
  
  /* translator: this is a module name */
  static const char *modulename = gettext_noop("sorter");
--- 14,21 ----
   *-------------------------------------------------------------------------
   */
  #include "pg_backup_archiver.h"
! #include "misc.h"
! #include "parallel.h"
  
  /* translator: this is a module name */
  static const char *modulename = gettext_noop("sorter");
*** a/src/bin/pg_dump/pg_dumpall.c
--- b/src/bin/pg_dump/pg_dumpall.c
***************
*** 63,68 **** static PGresult *executeQuery(PGconn *conn, const char *query);
--- 63,69 ----
  static void executeCommand(PGconn *conn, const char *query);
  
  static char pg_dump_bin[MAXPGPATH];
+ static const char *progname;
  static PQExpBuffer pgdumpopts;
  static char *connstr = "";
  static bool skip_acls = false;
***************
*** 82,87 **** static int	server_version;
--- 83,89 ----
  static FILE *OPF;
  static char *filename = NULL;
  
+ #define exit_nicely(code) exit(code)
  
  int
  main(int argc, char *argv[])
*** a/src/bin/pg_dump/pg_restore.c
--- b/src/bin/pg_dump/pg_restore.c
***************
*** 42,47 ****
--- 42,48 ----
  #include "pg_backup_archiver.h"
  
  #include "dumputils.h"
+ #include "misc.h"
  
  #include <ctype.h>
  
