]> granicus.if.org Git - postgresql/blobdiff - src/backend/postmaster/postmaster.c
Replace the BufMgrLock with separate locks on the lookup hashtable and
[postgresql] / src / backend / postmaster / postmaster.c
index 4bef3cefe005e89f3cb930ad9b733ab832f879cb..d84bf2775768ee2628cbc09ee84bfbff89959964 100644 (file)
@@ -7,7 +7,7 @@
  *       message to setup a backend process.
  *
  *       The postmaster also manages system-wide operations such as
- *       startup and shutdown. The postmaster itself doesn't do those
+ *       startup and shutdown. The postmaster itself doesn't do those
  *       operations, mind you --- it just forks off a subprocess to do them
  *       at the right times.  It also takes care of resetting the system
  *       if a backend crashes.
  *       clients.
  *
  *
- * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.423 2004/08/29 04:12:46 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.445 2005/02/22 04:36:36 momjian Exp $
  *
  * NOTES
  *
@@ -58,7 +58,7 @@
  * Error Reporting:
  *             Use write_stderr() only for reporting "interactive" errors
  *             (essentially, bogus arguments on the command line).  Once the
- *             postmaster is launched, use ereport().  In particular, don't use
+ *             postmaster is launched, use ereport().  In particular, don't use
  *             write_stderr() for anything that occurs after pmdaemonize.
  *
  *-------------------------------------------------------------------------
@@ -92,6 +92,7 @@
 #include <DNSServiceDiscovery/DNSServiceDiscovery.h>
 #endif
 
+#include "catalog/pg_control.h"
 #include "catalog/pg_database.h"
 #include "commands/async.h"
 #include "lib/dllist.h"
 #include "bootstrap/bootstrap.h"
 #include "pgstat.h"
 
+#ifdef EXEC_BACKEND
+#include "storage/spin.h"
+#endif
+
 
 /*
  * List of active backends (or child processes anyway; we don't actually
@@ -163,7 +168,7 @@ int                 ReservedBackends;
 static const char *progname = NULL;
 
 /* The socket(s) we're listening to. */
-#define MAXLISTEN      10
+#define MAXLISTEN      64
 static int     ListenSocket[MAXLISTEN];
 
 /*
@@ -223,8 +228,6 @@ bool                ClientAuthInProgress = false;           /* T during new-client
  */
 static unsigned int random_seed = 0;
 
-static int     debug_flag = 0;
-
 extern char *optarg;
 extern int     optind,
                        opterr;
@@ -236,11 +239,11 @@ extern int        optreset;
 /*
  * postmaster.c - function prototypes
  */
-static void checkDataDir(const char *checkdir);
-static bool onlyConfigSpecified(const char *checkdir);
+static void checkDataDir(void);
+
 #ifdef USE_RENDEZVOUS
 static void reg_reply(DNSServiceRegistrationReplyErrorType errorCode,
-                                         void *context);
+                 void *context);
 #endif
 static void pmdaemonize(void);
 static Port *ConnCreate(int serverFd);
@@ -275,7 +278,6 @@ static pid_t StartChildProcess(int xlop);
 #ifdef EXEC_BACKEND
 
 #ifdef WIN32
-static pid_t win32_forkexec(const char *path, char *argv[]);
 static void win32_AddChild(pid_t pid, HANDLE handle);
 static void win32_RemoveChild(pid_t pid);
 static pid_t win32_waitpid(int *exitstatus);
@@ -285,19 +287,74 @@ static pid_t *win32_childPIDArray;
 static HANDLE *win32_childHNDArray;
 static unsigned long win32_numChildren = 0;
 
-HANDLE PostmasterHandle;
+HANDLE         PostmasterHandle;
 #endif
 
 static pid_t backend_forkexec(Port *port);
 static pid_t internal_forkexec(int argc, char *argv[], Port *port);
 
-static void read_backend_variables(char *filename, Port *port);
-static bool write_backend_variables(char *filename, Port *port);
+/* Type for a socket that can be inherited to a client process */
+#ifdef WIN32
+typedef struct
+{
+       SOCKET origsocket; /* Original socket value, or -1 if not a socket */
+       WSAPROTOCOL_INFO wsainfo;
+} InheritableSocket;
+#else
+typedef int InheritableSocket;
+#endif
+
+typedef struct LWLock LWLock;  /* ugly kluge */
+
+/*
+ * Structure contains all variables passed to exec:ed backends
+ */
+typedef struct
+{
+       Port port;
+       InheritableSocket portsocket;
+       char DataDir[MAXPGPATH];
+       int ListenSocket[MAXLISTEN];
+       long MyCancelKey;
+       unsigned long UsedShmemSegID;
+       void *UsedShmemSegAddr;
+       slock_t *ShmemLock;
+       slock_t *ShmemIndexLock;
+       VariableCache ShmemVariableCache;
+       void *ShmemIndexAlloc;
+       Backend *ShmemBackendArray;
+       LWLock *LWLockArray;
+       slock_t *ProcStructLock;
+       InheritableSocket pgStatSock;
+       InheritableSocket pgStatPipe0;
+       InheritableSocket pgStatPipe1;
+       pid_t PostmasterPid;
+#ifdef WIN32
+       HANDLE PostmasterHandle;
+       HANDLE initial_signal_pipe;
+       HANDLE syslogPipe[2];
+#else
+       int syslogPipe[2];
+#endif
+       char my_exec_path[MAXPGPATH];
+       char ExtraOptions[MAXPGPATH];
+       char lc_collate[LOCALE_NAME_BUFLEN];
+       char lc_ctype[LOCALE_NAME_BUFLEN];
+} BackendParameters;
+
+static void read_backend_variables(char *id, Port *port);
+static void restore_backend_variables(BackendParameters *param, Port *port);
+#ifndef WIN32
+static bool save_backend_variables(BackendParameters *param, Port *port);
+#else
+static bool save_backend_variables(BackendParameters *param, Port *port,
+                                                                  HANDLE childProcess, pid_t childPid);
+#endif
 
 static void ShmemBackendArrayAdd(Backend *bn);
 static void ShmemBackendArrayRemove(pid_t pid);
 
-#endif /* EXEC_BACKEND */
+#endif   /* EXEC_BACKEND */
 
 #define StartupDataBase()              StartChildProcess(BS_XLOG_STARTUP)
 #define StartBackgroundWriter() StartChildProcess(BS_XLOG_BGWRITER)
@@ -311,10 +368,11 @@ PostmasterMain(int argc, char *argv[])
 {
        int                     opt;
        int                     status;
-       char       *userPGDATA = NULL;
+       char       *userDoption = NULL;
        int                     i;
 
-       progname = get_progname(argv[0]);
+       /* This will call exit() if strdup() fails. */
+       progname = get_progname(argv[0]);       
 
        MyProcPid = PostmasterPid = getpid();
 
@@ -338,6 +396,11 @@ PostmasterMain(int argc, char *argv[])
                }
        }
 
+#ifdef WIN32
+       /* Start our win32 signal implementation */
+       pgwin32_signal_initialize();
+#endif
+
        /*
         * for security, no dir or file created can be group or other
         * accessible
@@ -375,8 +438,6 @@ PostmasterMain(int argc, char *argv[])
         */
        InitializeGUCOptions();
 
-       userPGDATA = getenv("PGDATA");          /* default value */
-       
        opterr = 1;
 
        while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1)
@@ -400,20 +461,11 @@ PostmasterMain(int argc, char *argv[])
                                /* Can no longer set the backend executable file to use. */
                                break;
                        case 'D':
-                               userPGDATA = optarg;
+                               userDoption = optarg;
                                break;
                        case 'd':
-                               {
-                                       /* Turn on debugging for the postmaster. */
-                                       char       *debugstr = palloc(strlen("debug") + strlen(optarg) + 1);
-
-                                       sprintf(debugstr, "debug%s", optarg);
-                                       SetConfigOption("log_min_messages", debugstr,
-                                                                       PGC_POSTMASTER, PGC_S_ARGV);
-                                       pfree(debugstr);
-                                       debug_flag = atoi(optarg);
-                                       break;
-                               }
+                               set_debug_options(atoi(optarg), PGC_POSTMASTER, PGC_S_ARGV);
+                               break;
                        case 'F':
                                SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
                                break;
@@ -453,7 +505,8 @@ PostmasterMain(int argc, char *argv[])
                        case 'o':
 
                                /*
-                                * Other options to pass to the backend on the command line
+                                * Other options to pass to the backend on the command
+                                * line
                                 */
                                snprintf(ExtraOptions + strlen(ExtraOptions),
                                                 sizeof(ExtraOptions) - strlen(ExtraOptions),
@@ -529,62 +582,15 @@ PostmasterMain(int argc, char *argv[])
                ExitPostmaster(1);
        }
 
-       if (userPGDATA)
-       {
-               userPGDATA = strdup(userPGDATA);
-               canonicalize_path(userPGDATA);
-       }
-
-       if (onlyConfigSpecified(userPGDATA))
-       {
-               /*
-                *      It is either a file name or a directory with no
-                *      global/pg_control file, and hence not a data directory.
-                */
-               user_pgconfig = userPGDATA;
-               ProcessConfigFile(PGC_POSTMASTER);
-
-               if (!guc_pgdata)        /* Got a pgdata from the config file? */
-               {
-                       write_stderr("%s does not know where to find the database system data.\n"
-                                                "This should be specified as \"pgdata\" in %s%s.\n",
-                                                progname, userPGDATA,
-                                                user_pgconfig_is_dir ? "/postgresql.conf" : "");
-                       ExitPostmaster(2);
-               }
-               checkDataDir(guc_pgdata);
-               SetDataDir(guc_pgdata);
-       }
-       else
-       {
-               /* Now we can set the data directory, and then read postgresql.conf. */
-               checkDataDir(userPGDATA);
-               SetDataDir(userPGDATA);
-               ProcessConfigFile(PGC_POSTMASTER);
-       }
-
-       if (external_pidfile)
-       {
-               FILE *fpidfile = fopen(external_pidfile, "w");
-
-               if (fpidfile)
-               {
-                       fprintf(fpidfile, "%d\n", MyProcPid);
-                       fclose(fpidfile);
-                       /* Should we remove the pid file on postmaster exit? */
-               }
-               else
-                       fprintf(stderr,
-                               gettext("%s could not write to external pid file %s\n"),
-                               progname, external_pidfile);
-       }
-
-       /* If timezone is not set, determine what the OS uses */
-       pg_timezone_initialize();
+       /*
+        * Locate the proper configuration files and data directory, and
+        * read postgresql.conf for the first time.
+        */
+       if (!SelectConfigFiles(userDoption, progname))
+               ExitPostmaster(2);
 
-#ifdef EXEC_BACKEND
-       write_nondefault_variables(PGC_POSTMASTER);
-#endif
+       /* Verify that DataDir looks reasonable */
+       checkDataDir();
 
        /*
         * Check for invalid combinations of GUC settings.
@@ -645,8 +651,8 @@ PostmasterMain(int argc, char *argv[])
        if (find_other_exec(argv[0], "postgres", PG_VERSIONSTR,
                                                postgres_exec_path) < 0)
                ereport(FATAL,
-                               (errmsg("%s: could not locate matching postgres executable",
-                                               progname)));
+                        (errmsg("%s: could not locate matching postgres executable",
+                                        progname)));
 #endif
 
        /*
@@ -679,8 +685,8 @@ PostmasterMain(int argc, char *argv[])
         * We want to do this before we try to grab the input sockets, because
         * the data directory interlock is more reliable than the socket-file
         * interlock (thanks to whoever decided to put socket files in /tmp
-        * :-(). For the same reason, it's best to grab the TCP socket(s) before
-        * the Unix socket.
+        * :-(). For the same reason, it's best to grab the TCP socket(s)
+        * before the Unix socket.
         */
        CreateDataDirLockFile(DataDir, true);
 
@@ -699,25 +705,25 @@ PostmasterMain(int argc, char *argv[])
 
        if (ListenAddresses)
        {
-               char *rawstring;
-               List *elemlist;
-               ListCell *l;
+               char       *rawstring;
+               List       *elemlist;
+               ListCell   *l;
 
                /* Need a modifiable copy of ListenAddresses */
                rawstring = pstrdup(ListenAddresses);
 
                /* Parse string into list of identifiers */
-               if (!SplitIdentifierString(rawstring, ',', &elemlist)) 
+               if (!SplitIdentifierString(rawstring, ',', &elemlist))
                {
                        /* syntax error in list */
                        ereport(FATAL,
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                        errmsg("invalid list syntax for \"listen_addresses\"")));
+                               errmsg("invalid list syntax for \"listen_addresses\"")));
                }
 
                foreach(l, elemlist)
                {
-                       char *curhost = (char *) lfirst(l);
+                       char       *curhost = (char *) lfirst(l);
 
                        if (strcmp(curhost, "*") == 0)
                                status = StreamServerPort(AF_UNSPEC, NULL,
@@ -790,6 +796,7 @@ PostmasterMain(int argc, char *argv[])
        BackendList = DLNewList();
 
 #ifdef WIN32
+
        /*
         * Initialize the child pid/HANDLE arrays for signal handling.
         */
@@ -814,8 +821,8 @@ PostmasterMain(int argc, char *argv[])
                                                TRUE,
                                                DUPLICATE_SAME_ACCESS) == 0)
                ereport(FATAL,
-                               (errmsg_internal("could not duplicate postmaster handle: %d",
-                                                                (int) GetLastError())));
+                       (errmsg_internal("could not duplicate postmaster handle: error code %d",
+                                                        (int) GetLastError())));
 #endif
 
        /*
@@ -826,6 +833,28 @@ PostmasterMain(int argc, char *argv[])
        if (!CreateOptsFile(argc, argv, my_exec_path))
                ExitPostmaster(1);
 
+#ifdef EXEC_BACKEND
+       write_nondefault_variables(PGC_POSTMASTER);
+#endif
+
+       /*
+        * Write the external PID file if requested
+        */
+       if (external_pid_file)
+       {
+               FILE       *fpidfile = fopen(external_pid_file, "w");
+
+               if (fpidfile)
+               {
+                       fprintf(fpidfile, "%d\n", MyProcPid);
+                       fclose(fpidfile);
+                       /* Should we remove the pid file on postmaster exit? */
+               }
+               else
+                       write_stderr("%s: could not write external PID file \"%s\": %s\n",
+                                                progname, external_pid_file, strerror(errno));
+       }
+
        /*
         * Set up signal handlers for the postmaster process.
         *
@@ -862,9 +891,9 @@ PostmasterMain(int argc, char *argv[])
        /*
         * Reset whereToSendOutput from Debug (its starting state) to None.
         * This stops ereport from sending log messages to stderr unless
-        * Log_destination permits.  We don't do this until the postmaster
-        * is fully launched, since startup failures may as well be
-        * reported to stderr.
+        * Log_destination permits.  We don't do this until the postmaster is
+        * fully launched, since startup failures may as well be reported to
+        * stderr.
         */
        whereToSendOutput = None;
 
@@ -874,22 +903,16 @@ PostmasterMain(int argc, char *argv[])
        pgstat_init();
 
        /*
-        * Load cached files for client authentication.
+        * Load configuration files for client authentication.
         */
        load_hba();
        load_ident();
-       load_user();
-       load_group();
 
        /*
         * We're ready to rock and roll...
         */
        StartupPID = StartupDataBase();
 
-#ifdef EXEC_BACKEND
-       write_nondefault_variables(PGC_POSTMASTER);
-#endif
-
        status = ServerLoop();
 
        /*
@@ -902,64 +925,30 @@ PostmasterMain(int argc, char *argv[])
 }
 
 
-
-static bool
-onlyConfigSpecified(const char *checkdir)
-{
-       char    path[MAXPGPATH];
-       struct stat stat_buf;
-
-       if (checkdir == NULL)                   /* checkDataDir handles this */
-               return FALSE;
-
-       if (stat(checkdir, &stat_buf) == -1)    /* ditto */
-               return FALSE;
-
-       if (S_ISREG(stat_buf.st_mode))          /* It's a regular file, so assume it's explict */
-               return TRUE;
-       else if (S_ISDIR(stat_buf.st_mode))     /* It's a directory, is it a config or system dir? */
-       {
-               snprintf(path, MAXPGPATH, "%s/global/pg_control", checkdir);
-               /* If this is not found, it is a config-only directory */
-               if (stat(path, &stat_buf) == -1)
-                       return TRUE;
-       }
-       return FALSE;
-}
-
-
 /*
  * Validate the proposed data directory
  */
 static void
-checkDataDir(const char *checkdir)
+checkDataDir(void)
 {
        char            path[MAXPGPATH];
        FILE       *fp;
        struct stat stat_buf;
 
-       if (checkdir == NULL)
-       {
-               write_stderr("%s does not know where to find the database system data.\n"
-                                        "You must specify the directory that contains the database system\n"
-                                        "either by specifying the -D invocation option or by setting the\n"
-                                        "PGDATA environment variable.\n",
-                                        progname);
-               ExitPostmaster(2);
-       }
+       Assert(DataDir);
 
-       if (stat(checkdir, &stat_buf) == -1)
+       if (stat(DataDir, &stat_buf) != 0)
        {
                if (errno == ENOENT)
                        ereport(FATAL,
                                        (errcode_for_file_access(),
                                         errmsg("data directory \"%s\" does not exist",
-                                                       checkdir)));
+                                                       DataDir)));
                else
                        ereport(FATAL,
                                        (errcode_for_file_access(),
                         errmsg("could not read permissions of directory \"%s\": %m",
-                                       checkdir)));
+                                       DataDir)));
        }
 
        /*
@@ -969,19 +958,19 @@ checkDataDir(const char *checkdir)
         * be proper support for Unix-y file permissions.  Need to think of a
         * reasonable check to apply on Windows.
         */
-#if !defined(__CYGWIN__) && !defined(WIN32)
+#if !defined(WIN32) && !defined(__CYGWIN__)
        if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
                ereport(FATAL,
                                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                 errmsg("data directory \"%s\" has group or world access",
-                                               checkdir),
+                                               DataDir),
                                 errdetail("Permissions should be u=rwx (0700).")));
 #endif
 
        /* Look for PG_VERSION before looking for pg_control */
-       ValidatePgVersion(checkdir);
+       ValidatePgVersion(DataDir);
 
-       snprintf(path, sizeof(path), "%s/global/pg_control", checkdir);
+       snprintf(path, sizeof(path), "%s/global/pg_control", DataDir);
 
        fp = AllocateFile(path, PG_BINARY_R);
        if (fp == NULL)
@@ -989,7 +978,7 @@ checkDataDir(const char *checkdir)
                write_stderr("%s: could not find the database system\n"
                                         "Expected to find it in the directory \"%s\",\n"
                                         "but could not open file \"%s\": %s\n",
-                                        progname, checkdir, path, strerror(errno));
+                                        progname, DataDir, path, strerror(errno));
                ExitPostmaster(2);
        }
        FreeFile(fp);
@@ -1006,8 +995,7 @@ reg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context)
 {
 
 }
-
-#endif /* USE_RENDEZVOUS */
+#endif   /* USE_RENDEZVOUS */
 
 
 /*
@@ -1046,7 +1034,7 @@ pmdaemonize(void)
        setitimer(ITIMER_PROF, &prof_itimer, NULL);
 #endif
 
-       MyProcPid = PostmasterPid = getpid();   /* reset PID vars to child */
+       MyProcPid = PostmasterPid = getpid();           /* reset PID vars to child */
 
 /* GH: If there's no setsid(), we hopefully don't need silent mode.
  * Until there's a better solution.
@@ -1064,10 +1052,10 @@ pmdaemonize(void)
        dup2(i, 1);
        dup2(i, 2);
        close(i);
-#else  /* WIN32 */
+#else                                                  /* WIN32 */
        /* not supported */
        elog(FATAL, "SilentMode not supported under WIN32");
-#endif /* WIN32 */
+#endif   /* WIN32 */
 }
 
 
@@ -1077,35 +1065,35 @@ pmdaemonize(void)
 static void
 usage(const char *progname)
 {
-       printf(gettext("%s is the PostgreSQL server.\n\n"), progname);
-       printf(gettext("Usage:\n  %s [OPTION]...\n\n"), progname);
-       printf(gettext("Options:\n"));
+       printf(_("%s is the PostgreSQL server.\n\n"), progname);
+       printf(_("Usage:\n  %s [OPTION]...\n\n"), progname);
+       printf(_("Options:\n"));
 #ifdef USE_ASSERT_CHECKING
-       printf(gettext("  -A 1|0          enable/disable run-time assert checking\n"));
+       printf(_("  -A 1|0          enable/disable run-time assert checking\n"));
 #endif
-       printf(gettext("  -B NBUFFERS     number of shared buffers\n"));
-       printf(gettext("  -c NAME=VALUE   set run-time parameter\n"));
-       printf(gettext("  -d 1-5          debugging level\n"));
-       printf(gettext("  -D DATADIR      database directory\n"));
-       printf(gettext("  -F              turn fsync off\n"));
-       printf(gettext("  -h HOSTNAME     host name or IP address to listen on\n"));
-       printf(gettext("  -i              enable TCP/IP connections\n"));
-       printf(gettext("  -k DIRECTORY    Unix-domain socket location\n"));
+       printf(_("  -B NBUFFERS     number of shared buffers\n"));
+       printf(_("  -c NAME=VALUE   set run-time parameter\n"));
+       printf(_("  -d 1-5          debugging level\n"));
+       printf(_("  -D DATADIR      database directory\n"));
+       printf(_("  -F              turn fsync off\n"));
+       printf(_("  -h HOSTNAME     host name or IP address to listen on\n"));
+       printf(_("  -i              enable TCP/IP connections\n"));
+       printf(_("  -k DIRECTORY    Unix-domain socket location\n"));
 #ifdef USE_SSL
-       printf(gettext("  -l              enable SSL connections\n"));
+       printf(_("  -l              enable SSL connections\n"));
 #endif
-       printf(gettext("  -N MAX-CONNECT  maximum number of allowed connections\n"));
-       printf(gettext("  -o OPTIONS      pass \"OPTIONS\" to each server process\n"));
-       printf(gettext("  -p PORT         port number to listen on\n"));
-       printf(gettext("  -S              silent mode (start in background without logging output)\n"));
-       printf(gettext("  --help          show this help, then exit\n"));
-       printf(gettext("  --version       output version information, then exit\n"));
-
-       printf(gettext("\nDeveloper options:\n"));
-       printf(gettext("  -n              do not reinitialize shared memory after abnormal exit\n"));
-       printf(gettext("  -s              send SIGSTOP to all backend servers if one dies\n"));
-
-       printf(gettext("\nPlease read the documentation for the complete list of run-time\n"
+       printf(_("  -N MAX-CONNECT  maximum number of allowed connections\n"));
+       printf(_("  -o OPTIONS      pass \"OPTIONS\" to each server process\n"));
+       printf(_("  -p PORT         port number to listen on\n"));
+       printf(_("  -S              silent mode (start in background without logging output)\n"));
+       printf(_("  --help          show this help, then exit\n"));
+       printf(_("  --version       output version information, then exit\n"));
+
+       printf(_("\nDeveloper options:\n"));
+       printf(_("  -n              do not reinitialize shared memory after abnormal exit\n"));
+       printf(_("  -s              send SIGSTOP to all backend servers if one dies\n"));
+
+       printf(_("\nPlease read the documentation for the complete list of run-time\n"
                                   "configuration settings and how to set them on the command line or in\n"
                                   "the configuration file.\n\n"
                                   "Report bugs to <pgsql-bugs@postgresql.org>.\n"));
@@ -1143,7 +1131,8 @@ ServerLoop(void)
                 * Wait for something to happen.
                 *
                 * We wait at most one minute, to ensure that the other background
-                * tasks handled below get done even when no requests are arriving.
+                * tasks handled below get done even when no requests are
+                * arriving.
                 */
                memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
 
@@ -1178,7 +1167,8 @@ ServerLoop(void)
                if (selres > 0)
                {
                        /*
-                        * Select a random seed at the time of first receiving a request.
+                        * Select a random seed at the time of first receiving a
+                        * request.
                         */
                        while (random_seed == 0)
                        {
@@ -1186,8 +1176,9 @@ ServerLoop(void)
 
                                /*
                                 * We are not sure how much precision is in tv_usec, so we
-                                * swap the nibbles of 'later' and XOR them with 'earlier'. On
-                                * the off chance that the result is 0, we loop until it isn't.
+                                * swap the high and low 16 bits of 'later' and XOR them with
+                                * 'earlier'. On the off chance that the result is 0, we
+                                * loop until it isn't.
                                 */
                                random_seed = earlier.tv_usec ^
                                        ((later.tv_usec << 16) |
@@ -1206,8 +1197,8 @@ ServerLoop(void)
                                                BackendStartup(port);
 
                                                /*
-                                                * We no longer need the open socket or port structure
-                                                * in this process
+                                                * We no longer need the open socket or port
+                                                * structure in this process
                                                 */
                                                StreamClose(port->sock);
                                                ConnFree(port);
@@ -1221,8 +1212,8 @@ ServerLoop(void)
                        SysLoggerPID = SysLogger_Start();
 
                /*
-                * If no background writer process is running, and we are not in
-                * state that prevents it, start one.  It doesn't matter if this
+                * If no background writer process is running, and we are not in a
+                * state that prevents it, start one.  It doesn't matter if this
                 * fails, we'll just try again later.
                 */
                if (BgWriterPID == 0 && StartupPID == 0 && !FatalError)
@@ -1234,18 +1225,19 @@ ServerLoop(void)
                }
 
                /* If we have lost the archiver, try to start a new one */
-               if (XLogArchivingActive() && PgArchPID == 0 && 
-            StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
+               if (XLogArchivingActive() && PgArchPID == 0 &&
+                       StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
                        PgArchPID = pgarch_start();
+
                /* If we have lost the stats collector, try to start a new one */
                if (PgStatPID == 0 &&
                        StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
                        PgStatPID = pgstat_start();
 
                /*
-                * Touch the socket and lock file at least every ten minutes, to ensure
-                * that they are not removed by overzealous /tmp-cleaning tasks.
+                * Touch the socket and lock file at least every ten minutes, to
+                * ensure that they are not removed by overzealous /tmp-cleaning
+                * tasks.
                 */
                now = time(NULL);
                if (now - last_touch_time >= 10 * 60)
@@ -1803,6 +1795,8 @@ SIGHUP_handler(SIGNAL_ARGS)
                if (SysLoggerPID != 0)
                        kill(SysLoggerPID, SIGHUP);
                /* PgStatPID does not currently need SIGHUP */
+
+               /* Reload authentication config files too */
                load_hba();
                load_ident();
 
@@ -1835,6 +1829,7 @@ pmdie(SIGNAL_ARGS)
        switch (postgres_signal_arg)
        {
                case SIGTERM:
+
                        /*
                         * Smart Shutdown:
                         *
@@ -1869,6 +1864,7 @@ pmdie(SIGNAL_ARGS)
                        break;
 
                case SIGINT:
+
                        /*
                         * Fast Shutdown:
                         *
@@ -1896,8 +1892,8 @@ pmdie(SIGNAL_ARGS)
                        /*
                         * No children left. Begin shutdown of data base system.
                         *
-                        * Note: if we previously got SIGTERM then we may send SIGUSR2
-                        * to the bgwriter a second time here.  This should be harmless.
+                        * Note: if we previously got SIGTERM then we may send SIGUSR2 to
+                        * the bgwriter a second time here.  This should be harmless.
                         */
                        if (StartupPID != 0 || FatalError)
                                break;                  /* let reaper() handle this */
@@ -1916,6 +1912,7 @@ pmdie(SIGNAL_ARGS)
                        break;
 
                case SIGQUIT:
+
                        /*
                         * Immediate Shutdown:
                         *
@@ -1979,14 +1976,14 @@ reaper(SIGNAL_ARGS)
        while ((pid = win32_waitpid(&exitstatus)) > 0)
        {
                /*
-                * We need to do this here, and not in CleanupBackend, since this is
-                * to be called on all children when we are done with them. Could
-                * move to LogChildExit, but that seems like asking for future
-                * trouble...
+                * We need to do this here, and not in CleanupBackend, since this
+                * is to be called on all children when we are done with them.
+                * Could move to LogChildExit, but that seems like asking for
+                * future trouble...
                 */
                win32_RemoveChild(pid);
-#endif /* WIN32 */
-#endif /* HAVE_WAITPID */
+#endif   /* WIN32 */
+#endif   /* HAVE_WAITPID */
 
                /*
                 * Check if this child was a startup process.
@@ -1996,7 +1993,7 @@ reaper(SIGNAL_ARGS)
                        StartupPID = 0;
                        if (exitstatus != 0)
                        {
-                               LogChildExit(LOG, gettext("startup process"),
+                               LogChildExit(LOG, _("startup process"),
                                                         pid, exitstatus);
                                ereport(LOG,
                                                (errmsg("aborting startup due to startup process failure")));
@@ -2004,12 +2001,21 @@ reaper(SIGNAL_ARGS)
                        }
 
                        /*
-                        * Startup succeeded - we are done with system startup or recovery.
+                        * Startup succeeded - we are done with system startup or
+                        * recovery.
                         */
                        FatalError = false;
 
                        /*
-                        * Crank up the background writer.  It doesn't matter if this
+                        * Load the flat user/group files into postmaster's caches.
+                        * The startup process has recomputed these from the database
+                        * contents, so we wait till it finishes before loading them.
+                        */
+                       load_user();
+                       load_group();
+
+                       /*
+                        * Crank up the background writer.      It doesn't matter if this
                         * fails, we'll just try again later.
                         */
                        Assert(BgWriterPID == 0);
@@ -2017,16 +2023,18 @@ reaper(SIGNAL_ARGS)
 
                        /*
                         * Go to shutdown mode if a shutdown request was pending.
-                        * Otherwise, try to start the archiver and stats collector too.
+                        * Otherwise, try to start the archiver and stats collector
+                        * too.
                         */
                        if (Shutdown > NoShutdown && BgWriterPID != 0)
                                kill(BgWriterPID, SIGUSR2);
-                       else if (Shutdown == NoShutdown) {
-                    if (XLogArchivingActive() && PgArchPID == 0)
-                                       PgArchPID = pgarch_start();
-                    if (PgStatPID == 0)
-                                       PgStatPID = pgstat_start();
-            }
+                       else if (Shutdown == NoShutdown)
+                       {
+                               if (XLogArchivingActive() && PgArchPID == 0)
+                                       PgArchPID = pgarch_start();
+                               if (PgStatPID == 0)
+                                       PgStatPID = pgstat_start();
+                       }
 
                        continue;
                }
@@ -2041,37 +2049,38 @@ reaper(SIGNAL_ARGS)
                                !FatalError && !DLGetHead(BackendList))
                        {
                                /*
-                                * Normal postmaster exit is here: we've seen normal
-                                * exit of the bgwriter after it's been told to shut down.
-                                * We expect that it wrote a shutdown checkpoint.  (If
-                                * for some reason it didn't, recovery will occur on next
+                                * Normal postmaster exit is here: we've seen normal exit
+                                * of the bgwriter after it's been told to shut down. We
+                                * expect that it wrote a shutdown checkpoint.  (If for
+                                * some reason it didn't, recovery will occur on next
                                 * postmaster start.)
                                 *
                                 * Note: we do not wait around for exit of the archiver or
                                 * stats processes.  They've been sent SIGQUIT by this
-                                * point, and in any case contain logic to commit hara-kiri
-                                * if they notice the postmaster is gone.
+                                * point, and in any case contain logic to commit
+                                * hara-kiri if they notice the postmaster is gone.
                                 */
                                ExitPostmaster(0);
                        }
+
                        /*
                         * Any unexpected exit of the bgwriter is treated as a crash.
                         */
                        HandleChildCrash(pid, exitstatus,
-                                                        gettext("background writer process"));
+                                                        _("background writer process"));
                        continue;
                }
 
                /*
-                * Was it the archiver?  If so, just try to start a new
-                * one; no need to force reset of the rest of the system.  (If fail,
-                * we'll try again in future cycles of the main loop.)
+                * Was it the archiver?  If so, just try to start a new one; no
+                * need to force reset of the rest of the system.  (If fail, we'll
+                * try again in future cycles of the main loop.)
                 */
                if (PgArchPID != 0 && pid == PgArchPID)
                {
                        PgArchPID = 0;
                        if (exitstatus != 0)
-                               LogChildExit(LOG, gettext("archiver process"),
+                               LogChildExit(LOG, _("archiver process"),
                                                         pid, exitstatus);
                        if (XLogArchivingActive() &&
                                StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
@@ -2080,15 +2089,15 @@ reaper(SIGNAL_ARGS)
                }
 
                /*
-                * Was it the statistics collector?  If so, just try to start a new
-                * one; no need to force reset of the rest of the system.  (If fail,
-                * we'll try again in future cycles of the main loop.)
+                * Was it the statistics collector?  If so, just try to start a
+                * new one; no need to force reset of the rest of the system.  (If
+                * fail, we'll try again in future cycles of the main loop.)
                 */
                if (PgStatPID != 0 && pid == PgStatPID)
                {
                        PgStatPID = 0;
                        if (exitstatus != 0)
-                               LogChildExit(LOG, gettext("statistics collector process"),
+                               LogChildExit(LOG, _("statistics collector process"),
                                                         pid, exitstatus);
                        if (StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
                                PgStatPID = pgstat_start();
@@ -2102,7 +2111,7 @@ reaper(SIGNAL_ARGS)
                        /* for safety's sake, launch new logger *first* */
                        SysLoggerPID = SysLogger_Start();
                        if (exitstatus != 0)
-                               LogChildExit(LOG, gettext("system logger process"),
+                               LogChildExit(LOG, _("system logger process"),
                                                         pid, exitstatus);
                        continue;
                }
@@ -2117,8 +2126,8 @@ reaper(SIGNAL_ARGS)
        {
                /*
                 * Wait for all important children to exit, then reset shmem and
-                * StartupDataBase.  (We can ignore the archiver and stats processes
-                * here since they are not connected to shmem.)
+                * StartupDataBase.  (We can ignore the archiver and stats
+                * processes here since they are not connected to shmem.)
                 */
                if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0)
                        goto reaper_done;
@@ -2165,11 +2174,11 @@ reaper_done:
  */
 static void
 CleanupBackend(int pid,
-                          int exitstatus)              /* child's exit status. */
+                          int exitstatus)      /* child's exit status. */
 {
        Dlelem     *curr;
 
-       LogChildExit(DEBUG2, gettext("server process"), pid, exitstatus);
+       LogChildExit(DEBUG2, _("server process"), pid, exitstatus);
 
        /*
         * If a backend dies in an ugly way (i.e. exit status not 0) then we
@@ -2179,7 +2188,7 @@ CleanupBackend(int pid,
         */
        if (exitstatus != 0)
        {
-               HandleChildCrash(pid, exitstatus, gettext("server process"));
+               HandleChildCrash(pid, exitstatus, _("server process"));
                return;
        }
 
@@ -2217,13 +2226,14 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
 
        /*
         * Make log entry unless there was a previous crash (if so, nonzero
-        * exit status is to be expected in SIGQUIT response; don't clutter log)
+        * exit status is to be expected in SIGQUIT response; don't clutter
+        * log)
         */
        if (!FatalError)
        {
                LogChildExit(LOG, procname, pid, exitstatus);
                ereport(LOG,
-                               (errmsg("terminating any other active server processes")));
+                         (errmsg("terminating any other active server processes")));
        }
 
        /* Process regular backends */
@@ -2414,7 +2424,7 @@ BackendStartup(Port *port)
 
        pid = backend_forkexec(port);
 
-#else /* !EXEC_BACKEND */
+#else                                                  /* !EXEC_BACKEND */
 
 #ifdef LINUX_PROFILE
 
@@ -2449,8 +2459,7 @@ BackendStartup(Port *port)
 
                proc_exit(BackendRun(port));
        }
-
-#endif /* EXEC_BACKEND */
+#endif   /* EXEC_BACKEND */
 
        if (pid < 0)
        {
@@ -2503,7 +2512,7 @@ report_fork_failure_to_client(Port *port, int errnum)
 
        /* Format the error message packet (always V2 protocol) */
        snprintf(buffer, sizeof(buffer), "E%s%s\n",
-                        gettext("could not fork new process for connection: "),
+                        _("could not fork new process for connection: "),
                         strerror(errnum));
 
        /* Set port to non-blocking.  Don't do send() if this fails */
@@ -2556,15 +2565,12 @@ static int
 BackendRun(Port *port)
 {
        int                     status;
-       struct timeval now;
-       struct timezone tz;
        char            remote_host[NI_MAXHOST];
        char            remote_port[NI_MAXSERV];
        char            remote_ps_data[NI_MAXHOST];
        char      **av;
        int                     maxac;
        int                     ac;
-       char            debugbuf[32];
        char            protobuf[32];
        int                     i;
 
@@ -2664,12 +2670,12 @@ BackendRun(Port *port)
        port->remote_port = strdup(remote_port);
 
        /*
-        * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.c
+        * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.conf
         * etcetera from the postmaster, and have to load them ourselves.
         * Build the PostmasterContext (which didn't exist before, in this
         * process) to contain the data.
         *
-        * FIXME: [fork/exec] Ugh.  Is there a way around this overhead?
+        * FIXME: [fork/exec] Ugh.      Is there a way around this overhead?
         */
 #ifdef EXEC_BACKEND
        Assert(PostmasterContext == NULL);
@@ -2735,9 +2741,7 @@ BackendRun(Port *port)
         * start a new random sequence in the random() library function.
         */
        random_seed = 0;
-       gettimeofday(&now, &tz);
-       srandom((unsigned int) now.tv_usec);
-
+       srandom((unsigned int) (MyProcPid ^ port->session_start.tv_usec));
 
        /* ----------------
         * Now, build the argv vector that will be given to PostgresMain.
@@ -2762,15 +2766,6 @@ BackendRun(Port *port)
 
        av[ac++] = "postgres";
 
-       /*
-        * Pass the requested debugging level along to the backend.
-        */
-       if (debug_flag > 0)
-       {
-               snprintf(debugbuf, sizeof(debugbuf), "-d%d", debug_flag);
-               av[ac++] = debugbuf;
-       }
-
        /*
         * Pass any backend switches specified with -o in the postmaster's own
         * command line.  We assume these are secure.  (It's OK to mangle
@@ -2816,7 +2811,7 @@ BackendRun(Port *port)
         */
        ereport(DEBUG3,
                        (errmsg_internal("%s child[%d]: starting with (",
-                                                        progname, getpid())));
+                                                        progname, (int)getpid())));
        for (i = 0; i < ac; ++i)
                ereport(DEBUG3,
                                (errmsg_internal("\t%s", av[i])));
@@ -2875,14 +2870,70 @@ backend_forkexec(Port *port)
        return internal_forkexec(ac, av, port);
 }
 
+#ifndef WIN32
+
+/*
+ * internal_forkexec non-win32 implementation
+ *
+ * - writes out backend variables to the parameter file
+ * - fork():s, and then exec():s the child process
+ */
 static pid_t
 internal_forkexec(int argc, char *argv[], Port *port)
 {
+       static unsigned long tmpBackendFileNum = 0;
        pid_t           pid;
        char            tmpfilename[MAXPGPATH];
+       BackendParameters param;
+       FILE       *fp;
+
+       if (!save_backend_variables(&param, port))
+               return -1;                              /* log made by save_backend_variables */
+
+       /* Calculate name for temp file */
+       Assert(DataDir);
+       snprintf(tmpfilename, MAXPGPATH, "%s/%s/%s.backend_var.%d.%lu",
+                        DataDir, PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
+                        MyProcPid, ++tmpBackendFileNum);
 
-       if (!write_backend_variables(tmpfilename, port))
-               return -1;                              /* log made by write_backend_variables */
+       /* Open file */
+       fp = AllocateFile(tmpfilename, PG_BINARY_W);
+       if (!fp)
+       {
+               /* As per OpenTemporaryFile... */
+               char            dirname[MAXPGPATH];
+
+               snprintf(dirname, MAXPGPATH, "%s/%s", DataDir, PG_TEMP_FILES_DIR);
+               mkdir(dirname, S_IRWXU);
+
+               fp = AllocateFile(tmpfilename, PG_BINARY_W);
+               if (!fp)
+               {
+                       ereport(LOG,
+                                       (errcode_for_file_access(),
+                                        errmsg("could not create file \"%s\": %m",
+                                                       tmpfilename)));
+                       return -1;
+               }
+       }
+
+       if (fwrite(&param, sizeof(param), 1, fp) != 1)
+       {
+               ereport(LOG,
+                               (errcode_for_file_access(),
+                                errmsg("could not write to file \"%s\": %m", tmpfilename)));
+               FreeFile(fp);
+               return -1;
+       }
+
+       /* Release file */
+       if (FreeFile(fp))
+       {
+               ereport(LOG,
+                               (errcode_for_file_access(),
+                                errmsg("could not write to file \"%s\": %m", tmpfilename)));
+               return -1;
+       }
 
        /* Make sure caller set up argv properly */
        Assert(argc >= 3);
@@ -2893,26 +2944,200 @@ internal_forkexec(int argc, char *argv[], Port *port)
        /* Insert temp file name after -fork argument */
        argv[2] = tmpfilename;
 
-#ifdef WIN32
-       pid = win32_forkexec(postgres_exec_path, argv);
-#else
        /* Fire off execv in child */
        if ((pid = fork()) == 0)
        {
                if (execv(postgres_exec_path, argv) < 0)
                {
                        ereport(LOG,
-                                       (errmsg("could not exec backend process \"%s\": %m",
+                                       (errmsg("could not execute server process \"%s\": %m",
                                                        postgres_exec_path)));
                        /* We're already in the child process here, can't return */
                        exit(1);
                }
        }
-#endif
 
-       return pid;                                     /* Parent returns pid, or -1 on fork failure */
+       return pid;                                     /* Parent returns pid, or -1 on fork
+                                                                * failure */
+}
+
+#else /* WIN32 */
+
+/*
+ * internal_forkexec win32 implementation
+ *
+ * - starts backend using CreateProcess(), in suspended state
+ * - writes out backend variables to the parameter file
+ *  - during this, duplicates handles and sockets required for
+ *    inheritance into the new process
+ * - resumes execution of the new process once the backend parameter
+ *   file is complete.
+ */
+static pid_t
+internal_forkexec(int argc, char *argv[], Port *port)
+{
+       STARTUPINFO si;
+       PROCESS_INFORMATION pi;
+       int                     i;
+       int                     j;
+       char            cmdLine[MAXPGPATH * 2];
+       HANDLE          childHandleCopy;
+       HANDLE          waiterThread;
+       HANDLE      paramHandle;
+       BackendParameters *param;
+       SECURITY_ATTRIBUTES sa;
+       char        paramHandleStr[32];
+
+       /* Make sure caller set up argv properly */
+       Assert(argc >= 3);
+       Assert(argv[argc] == NULL);
+       Assert(strncmp(argv[1], "-fork", 5) == 0);
+       Assert(argv[2] == NULL);
+
+       /* Set up shared memory for parameter passing */
+       ZeroMemory(&sa,sizeof(sa));
+       sa.nLength = sizeof(sa);
+       sa.bInheritHandle = TRUE;
+       paramHandle = CreateFileMapping(INVALID_HANDLE_VALUE,
+                                                                       &sa,
+                                                                       PAGE_READWRITE,
+                                                                       0,
+                                                                       sizeof(BackendParameters),
+                                                                       NULL);
+       if (paramHandle == INVALID_HANDLE_VALUE)
+       {
+               elog(LOG, "could not create backend parameter file mapping: error code %d",
+                        (int) GetLastError());
+               return -1;
+       }
+
+       param = MapViewOfFile(paramHandle, FILE_MAP_WRITE, 0, 0, sizeof(BackendParameters));
+       if (!param)
+       {
+               elog(LOG, "could not map backend parameter memory: error code %d",
+                        (int) GetLastError());
+               CloseHandle(paramHandle);
+               return -1;
+       }
+
+       /* Insert temp file name after -fork argument */
+       sprintf(paramHandleStr, "%lu", (DWORD)paramHandle);
+       argv[2] = paramHandleStr;
+
+       /* Format the cmd line */
+       cmdLine[sizeof(cmdLine) - 1] = '\0';
+       cmdLine[sizeof(cmdLine) - 2] = '\0';
+       snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\"", postgres_exec_path);
+       i = 0;
+       while (argv[++i] != NULL)
+       {
+               j = strlen(cmdLine);
+               snprintf(cmdLine + j, sizeof(cmdLine) - 1 - j, " \"%s\"", argv[i]);
+       }
+       if (cmdLine[sizeof(cmdLine) - 2] != '\0')
+       {
+               elog(LOG, "subprocess command line too long");
+               return -1;
+       }
+
+       memset(&pi, 0, sizeof(pi));
+       memset(&si, 0, sizeof(si));
+       si.cb = sizeof(si);
+       /*
+        * Create the subprocess in a suspended state. This will be resumed
+        * later, once we have written out the parameter file.
+        */
+       if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_SUSPENDED,
+                                          NULL, NULL, &si, &pi))
+       {
+               elog(LOG, "CreateProcess call failed: %m (error code %d)",
+                        (int) GetLastError());
+               return -1;
+       }
+
+       if (!save_backend_variables(param, port, pi.hProcess, pi.dwProcessId))
+       {
+               /*
+                * log made by save_backend_variables, but we have to clean
+                * up the mess with the half-started process
+                */
+               if (!TerminateProcess(pi.hProcess, 255))
+                       ereport(ERROR,
+                                       (errmsg_internal("could not terminate unstarted process: error code %d",
+                                                                        (int) GetLastError())));
+               CloseHandle(pi.hProcess);
+               CloseHandle(pi.hThread);
+               return -1;                              /* log made by save_backend_variables */
+       }
+
+       /* Drop the shared memory that is now inherited to the backend */
+       if (!UnmapViewOfFile(param))
+               elog(LOG, "could not unmap view of backend parameter file: error code %d",
+                        (int) GetLastError());
+       if (!CloseHandle(paramHandle))
+               elog(LOG, "could not close handle to backend parameter file: error code %d",
+                        (int) GetLastError());
+
+       /*
+        * Now that the backend variables are written out, we start the
+        * child thread so it can start initializing while we set up
+        * the rest of the parent state.
+        */
+       if (ResumeThread(pi.hThread) == -1)
+       {
+               if (!TerminateProcess(pi.hProcess, 255))
+               {
+                       ereport(ERROR,
+                                       (errmsg_internal("could not terminate unstartable process: error code %d",
+                                                                        (int) GetLastError())));
+                       CloseHandle(pi.hProcess);
+                       CloseHandle(pi.hThread);
+                       return -1;
+               }
+               CloseHandle(pi.hProcess);
+               CloseHandle(pi.hThread);
+               ereport(ERROR,
+                               (errmsg_internal("could not resume thread of unstarted process: error code %d",
+                                                                (int) GetLastError())));
+               return -1;
+       }
+
+       if (!IsUnderPostmaster)
+       {
+               /* We are the Postmaster creating a child... */
+               win32_AddChild(pi.dwProcessId, pi.hProcess);
+       }
+
+       /* Set up the thread to handle the SIGCHLD for this process */
+       if (DuplicateHandle(GetCurrentProcess(),
+                                               pi.hProcess,
+                                               GetCurrentProcess(),
+                                               &childHandleCopy,
+                                               0,
+                                               FALSE,
+                                               DUPLICATE_SAME_ACCESS) == 0)
+               ereport(FATAL,
+                               (errmsg_internal("could not duplicate child handle: error code %d",
+                                                                (int) GetLastError())));
+
+       waiterThread = CreateThread(NULL, 64 * 1024, win32_sigchld_waiter,
+                                                               (LPVOID) childHandleCopy, 0, NULL);
+       if (!waiterThread)
+               ereport(FATAL,
+                  (errmsg_internal("could not create sigchld waiter thread: error code %d",
+                                                       (int) GetLastError())));
+       CloseHandle(waiterThread);
+
+       if (IsUnderPostmaster)
+               CloseHandle(pi.hProcess);
+       CloseHandle(pi.hThread);
+
+       return pi.dwProcessId;
 }
 
+#endif /* WIN32 */
+
+
 /*
  * SubPostmasterMain -- Get the fork/exec'd process into a state equivalent
  *                     to what it would be if we'd simply forked on Unix, and then
@@ -2937,20 +3162,42 @@ SubPostmasterMain(int argc, char *argv[])
        /* In EXEC_BACKEND case we will not have inherited these settings */
        IsPostmasterEnvironment = true;
        whereToSendOutput = None;
-       pqinitmask();
-       PG_SETMASK(&BlockSig);
 
-       /* Setup essential subsystems */
+       /* Setup essential subsystems (to ensure elog() behaves sanely) */
        MemoryContextInit();
        InitializeGUCOptions();
 
+       /* Read in the variables file */
+       memset(&port, 0, sizeof(Port));
+       read_backend_variables(argv[2], &port);
+
        /* Check we got appropriate args */
        if (argc < 3)
                elog(FATAL, "invalid subpostmaster invocation");
 
-       /* Read in file-based context */
-       memset(&port, 0, sizeof(Port));
-       read_backend_variables(argv[2], &port);
+       /*
+        * If appropriate, physically re-attach to shared memory segment.
+        * We want to do this before going any further to ensure that we
+        * can attach at the same address the postmaster used.
+        */
+       if (strcmp(argv[1], "-forkbackend") == 0 ||
+               strcmp(argv[1], "-forkboot") == 0)
+               PGSharedMemoryReAttach();
+
+       /*
+        * Start our win32 signal implementation. This has to be done
+        * after we read the backend variables, because we need to pick
+        * up the signal pipe from the parent process.
+        */
+#ifdef WIN32
+       pgwin32_signal_initialize();
+#endif
+
+       /* In EXEC_BACKEND case we will not have inherited these settings */
+       pqinitmask();
+       PG_SETMASK(&BlockSig);
+
+       /* Read in remaining GUC variables */
        read_nondefault_variables();
 
        /* Run backend or appropriate child */
@@ -2958,9 +3205,19 @@ SubPostmasterMain(int argc, char *argv[])
        {
                /* BackendRun will close sockets */
 
-               /* Attach process to shared segments */
+               /* Attach process to shared data structures */
                CreateSharedMemoryAndSemaphores(false, MaxBackends, 0);
 
+#ifdef USE_SSL
+               /*
+                *      Need to reinitialize the SSL library in the backend,
+                *      since the context structures contain function pointers
+                *      and cannot be passed through the parameter file.
+                */
+               if (EnableSSL)
+                       secure_initialize();
+#endif
+
                Assert(argc == 3);              /* shouldn't be any more args */
                proc_exit(BackendRun(&port));
        }
@@ -2969,7 +3226,7 @@ SubPostmasterMain(int argc, char *argv[])
                /* Close the postmaster's sockets */
                ClosePostmasterPorts(false);
 
-               /* Attach process to shared segments */
+               /* Attach process to shared data structures */
                CreateSharedMemoryAndSemaphores(false, MaxBackends, 0);
 
                BootstrapMain(argc - 2, argv + 2);
@@ -2998,8 +3255,8 @@ SubPostmasterMain(int argc, char *argv[])
        if (strcmp(argv[1], "-forkcol") == 0)
        {
                /*
-                * Do NOT close postmaster sockets here, because we are forking from
-                * pgstat buffer process, which already did it.
+                * Do NOT close postmaster sockets here, because we are forking
+                * from pgstat buffer process, which already did it.
                 */
 
                /* Do not want to attach to shared memory */
@@ -3021,7 +3278,7 @@ SubPostmasterMain(int argc, char *argv[])
        return 1;                                       /* shouldn't get here */
 }
 
-#endif /* EXEC_BACKEND */
+#endif   /* EXEC_BACKEND */
 
 
 /*
@@ -3082,9 +3339,9 @@ sigusr1_handler(SIGNAL_ARGS)
                         * Send SIGUSR1 to archiver process, to wake it up and begin
                         * archiving next transaction log file.
                         */
-            kill(PgArchPID, SIGUSR1);
+                       kill(PgArchPID, SIGUSR1);
                }
-    }
+       }
 
        PG_SETMASK(&UnBlockSig);
 
@@ -3186,9 +3443,7 @@ CountChildren(void)
        int                     cnt = 0;
 
        for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
-       {
                cnt++;
-       }
        return cnt;
 }
 
@@ -3196,7 +3451,7 @@ CountChildren(void)
 /*
  * StartChildProcess -- start a non-backend child process for the postmaster
  *
- * xlog determines what kind of child will be started.  All child types
+ * xlog determines what kind of child will be started. All child types
  * initially go to BootstrapMain, which will handle common setup.
  *
  * Return value of StartChildProcess is subprocess' PID, or 0 if failed
@@ -3209,6 +3464,7 @@ StartChildProcess(int xlop)
        char       *av[10];
        int                     ac = 0;
        char            xlbuf[32];
+
 #ifdef LINUX_PROFILE
        struct itimerval prof_itimer;
 #endif
@@ -3242,7 +3498,7 @@ StartChildProcess(int xlop)
 
        pid = postmaster_forkexec(ac, av);
 
-#else /* !EXEC_BACKEND */
+#else                                                  /* !EXEC_BACKEND */
 
 #ifdef LINUX_PROFILE
        /* see comments in BackendStartup */
@@ -3267,7 +3523,8 @@ StartChildProcess(int xlop)
                beos_backend_startup();
 #endif
 
-               IsUnderPostmaster = true;       /* we are a postmaster subprocess now */
+               IsUnderPostmaster = true;               /* we are a postmaster subprocess
+                                                                                * now */
 
                /* Close the postmaster's sockets */
                ClosePostmasterPorts(false);
@@ -3283,8 +3540,7 @@ StartChildProcess(int xlop)
                BootstrapMain(ac, av);
                ExitPostmaster(0);
        }
-
-#endif /* EXEC_BACKEND */
+#endif   /* EXEC_BACKEND */
 
        if (pid < 0)
        {
@@ -3304,7 +3560,7 @@ StartChildProcess(int xlop)
                                break;
                        case BS_XLOG_BGWRITER:
                                ereport(LOG,
-                                               (errmsg("could not fork background writer process: %m")));
+                               (errmsg("could not fork background writer process: %m")));
                                break;
                        default:
                                ereport(LOG,
@@ -3313,8 +3569,8 @@ StartChildProcess(int xlop)
                }
 
                /*
-                * fork failure is fatal during startup, but there's no need
-                * to choke immediately if starting other child types fails.
+                * fork failure is fatal during startup, but there's no need to
+                * choke immediately if starting other child types fails.
                 */
                if (xlop == BS_XLOG_STARTUP)
                        ExitPostmaster(1);
@@ -3348,7 +3604,7 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname)
 
        fprintf(fp, "%s", fullprogname);
        for (i = 1; i < argc; i++)
-               fprintf(fp, " '%s'", argv[i]);
+               fprintf(fp, " %s%s%s", SYSTEMQUOTE, argv[i], SYSTEMQUOTE);
        fputs("\n", fp);
 
        if (fclose(fp))
@@ -3364,191 +3620,279 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname)
 #ifdef EXEC_BACKEND
 
 /*
- * The following need to be available to the read/write_backend_variables
+ * The following need to be available to the save/restore_backend_variables
  * functions
  */
-#include "storage/spin.h"
-
 extern slock_t *ShmemLock;
 extern slock_t *ShmemIndexLock;
 extern void *ShmemIndexAlloc;
-typedef struct LWLock LWLock;
 extern LWLock *LWLockArray;
 extern slock_t *ProcStructLock;
 extern int     pgStatSock;
+extern int pgStatPipe[2];
 
-#define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp)
-#define read_var(var,fp)  fread((void*)&(var),sizeof(var),1,fp)
-#define write_array_var(var,fp) fwrite((void*)(var),sizeof(var),1,fp)
-#define read_array_var(var,fp)  fread((void*)(var),sizeof(var),1,fp)
+#ifndef WIN32
+#define write_inheritable_socket(dest, src, childpid) (*(dest) = (src))
+#define read_inheritable_socket(dest, src) (*(dest) = *(src))
+#else
+static void write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
+static void write_inheritable_socket(InheritableSocket *dest, SOCKET src,
+                                                                        pid_t childPid);
+static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
+#endif
 
+
+/* Save critical backend variables into the BackendParameters struct */
+#ifndef WIN32
+static bool
+save_backend_variables(BackendParameters *param, Port *port)
+#else
 static bool
-write_backend_variables(char *filename, Port *port)
+save_backend_variables(BackendParameters *param, Port *port,
+                                          HANDLE childProcess, pid_t childPid)
+#endif
 {
-       static unsigned long tmpBackendFileNum = 0;
-       FILE       *fp;
-       char            str_buf[MAXPGPATH];
+       memcpy(&param->port, port, sizeof(Port));
+       write_inheritable_socket(&param->portsocket, port->sock, childPid);
 
-       /* Calculate name for temp file in caller's buffer */
-       Assert(DataDir);
-       snprintf(filename, MAXPGPATH, "%s/%s/%s.backend_var.%d.%lu",
-                        DataDir, PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
-                        MyProcPid, ++tmpBackendFileNum);
+       StrNCpy(param->DataDir, DataDir, MAXPGPATH);
 
-       /* Open file */
-       fp = AllocateFile(filename, PG_BINARY_W);
-       if (!fp)
-       {
-               /* As per OpenTemporaryFile... */
-               char            dirname[MAXPGPATH];
+       memcpy(&param->ListenSocket, &ListenSocket, sizeof(ListenSocket));
 
-               snprintf(dirname, MAXPGPATH, "%s/%s", DataDir, PG_TEMP_FILES_DIR);
-               mkdir(dirname, S_IRWXU);
+       param->MyCancelKey = MyCancelKey;
 
-               fp = AllocateFile(filename, PG_BINARY_W);
-               if (!fp)
-               {
-                       ereport(LOG,
-                                       (errcode_for_file_access(),
-                                        errmsg("could not create file \"%s\": %m",
-                                                       filename)));
-                       return false;
-               }
-       }
+       param->UsedShmemSegID = UsedShmemSegID;
+       param->UsedShmemSegAddr = UsedShmemSegAddr;
 
-       /* Write vars */
-       write_var(port->sock, fp);
-       write_var(port->proto, fp);
-       write_var(port->laddr, fp);
-       write_var(port->raddr, fp);
-       write_var(port->canAcceptConnections, fp);
-       write_var(port->cryptSalt, fp);
-       write_var(port->md5Salt, fp);
+       param->ShmemLock = ShmemLock;
+       param->ShmemIndexLock = ShmemIndexLock;
+       param->ShmemVariableCache = ShmemVariableCache;
+       param->ShmemIndexAlloc = ShmemIndexAlloc;
+       param->ShmemBackendArray = ShmemBackendArray;
 
-       /*
-        * XXX FIXME later: writing these strings as MAXPGPATH bytes always is
-        * probably a waste of resources
-        */
+       param->LWLockArray = LWLockArray;
+       param->ProcStructLock = ProcStructLock;
+       write_inheritable_socket(&param->pgStatSock, pgStatSock, childPid);
+       write_inheritable_socket(&param->pgStatPipe0, pgStatPipe[0], childPid);
+       write_inheritable_socket(&param->pgStatPipe1, pgStatPipe[1], childPid);
 
-       StrNCpy(str_buf, DataDir, MAXPGPATH);
-       write_array_var(str_buf, fp);
+       param->PostmasterPid = PostmasterPid;
 
-       write_array_var(ListenSocket, fp);
+#ifdef WIN32
+       param->PostmasterHandle = PostmasterHandle;
+       write_duplicated_handle(&param->initial_signal_pipe,
+                                                       pgwin32_create_signal_listener(childPid),
+                                                       childProcess);
+#endif
 
-       write_var(MyCancelKey, fp);
+       memcpy(&param->syslogPipe, &syslogPipe, sizeof(syslogPipe));
 
-       write_var(UsedShmemSegID, fp);
-       write_var(UsedShmemSegAddr, fp);
+       StrNCpy(param->my_exec_path, my_exec_path, MAXPGPATH);
 
-       write_var(ShmemLock, fp);
-       write_var(ShmemIndexLock, fp);
-       write_var(ShmemVariableCache, fp);
-       write_var(ShmemIndexAlloc, fp);
-       write_var(ShmemBackendArray, fp);
+       StrNCpy(param->ExtraOptions, ExtraOptions, MAXPGPATH);
 
-       write_var(LWLockArray, fp);
-       write_var(ProcStructLock, fp);
-       write_var(pgStatSock, fp);
+       StrNCpy(param->lc_collate, setlocale(LC_COLLATE, NULL), LOCALE_NAME_BUFLEN);
+       StrNCpy(param->lc_ctype, setlocale(LC_CTYPE, NULL), LOCALE_NAME_BUFLEN);
 
-       write_var(debug_flag, fp);
-       write_var(PostmasterPid, fp);
-#ifdef WIN32
-       write_var(PostmasterHandle, fp);
-#endif
+       return true;
+}
 
-       write_var(syslogPipe[0], fp);
-       write_var(syslogPipe[1], fp);
 
-       StrNCpy(str_buf, my_exec_path, MAXPGPATH);
-       write_array_var(str_buf, fp);
+#ifdef WIN32
+/*
+ * Duplicate a handle for usage in a child process, and write the child
+ * process instance of the handle to the parameter file.
+ */
+static void
+write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
+{
+       HANDLE hChild = INVALID_HANDLE_VALUE;
+
+       if (!DuplicateHandle(GetCurrentProcess(),
+                                                src,
+                                                childProcess,
+                                                &hChild,
+                                                0,
+                                                TRUE,
+                                                DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
+               ereport(ERROR,
+                               (errmsg_internal("could not duplicate handle to be written to backend parameter file: error code %d",
+                                                                (int) GetLastError())));
 
-       write_array_var(ExtraOptions, fp);
+       *dest = hChild;
+}
 
-       StrNCpy(str_buf, setlocale(LC_COLLATE, NULL), MAXPGPATH);
-       write_array_var(str_buf, fp);
-       StrNCpy(str_buf, setlocale(LC_CTYPE, NULL), MAXPGPATH);
-       write_array_var(str_buf, fp);
+/*
+ * Duplicate a socket for usage in a child process, and write the resulting
+ * structure to the parameter file.
+ * This is required because a number of LSPs (Layered Service Providers) very
+ * common on Windows (antivirus, firewalls, download managers etc) break
+ * straight socket inheritance.
+ */
+static void
+write_inheritable_socket(InheritableSocket *dest, SOCKET src, pid_t childpid)
+{
+       dest->origsocket = src;
+       if (src != 0 && src != -1)
+       {
+               /* Actual socket */
+               if (WSADuplicateSocket(src, childpid, &dest->wsainfo) != 0)
+                       ereport(ERROR,
+                                       (errmsg("could not duplicate socket %d for use in backend: error code %d",
+                                                       src, WSAGetLastError())));
+       }
+}
 
-       /* Release file */
-       if (FreeFile(fp))
+/*
+ * Read a duplicate socket structure back, and get the socket descriptor.
+ */
+static void
+read_inheritable_socket(SOCKET *dest, InheritableSocket *src)
+{
+       SOCKET s;
+
+       if (src->origsocket == -1  || src->origsocket == 0)
        {
-               ereport(ERROR,
-                               (errcode_for_file_access(),
-                                errmsg("could not write to file \"%s\": %m", filename)));
-               return false;
+               /* Not a real socket! */
+               *dest = src->origsocket;
        }
+       else
+       {
+               /* Actual socket, so create from structure */
+               s = WSASocket(FROM_PROTOCOL_INFO,
+                                         FROM_PROTOCOL_INFO,
+                                         FROM_PROTOCOL_INFO,
+                                         &src->wsainfo,
+                                         0,
+                                         0);
+               if (s == INVALID_SOCKET)
+               {
+                       write_stderr("could not create inherited socket: error code %d\n",
+                                                WSAGetLastError());
+                       exit(1);
+               }
+               *dest = s;
 
-       return true;
+               /*
+                * To make sure we don't get two references to the same socket,
+                * close the original one. (This would happen when inheritance
+                * actually works..
+                */
+               closesocket(src->origsocket);
+       }
 }
+#endif
 
 static void
-read_backend_variables(char *filename, Port *port)
+read_backend_variables(char *id, Port *port)
 {
-       FILE       *fp;
-       char            str_buf[MAXPGPATH];
+       BackendParameters param;
+
+#ifndef WIN32
+       /* Non-win32 implementation reads from file */
+       FILE *fp;
 
        /* Open file */
-       fp = AllocateFile(filename, PG_BINARY_R);
+       fp = AllocateFile(id, PG_BINARY_R);
        if (!fp)
-               ereport(FATAL,
-                               (errcode_for_file_access(),
-                                errmsg("could not read from backend variables file \"%s\": %m",
-                                               filename)));
+       {
+               write_stderr("could not read from backend variables file \"%s\": %s\n",
+                                        id, strerror(errno));
+               exit(1);
+       }
 
-       /* Read vars */
-       read_var(port->sock, fp);
-       read_var(port->proto, fp);
-       read_var(port->laddr, fp);
-       read_var(port->raddr, fp);
-       read_var(port->canAcceptConnections, fp);
-       read_var(port->cryptSalt, fp);
-       read_var(port->md5Salt, fp);
+       if (fread(&param, sizeof(param), 1, fp) != 1)
+       {
+               write_stderr("could not read from backend variables file \"%s\": %s\n",
+                                        id, strerror(errno));
+               exit(1);
+       }
 
-       read_array_var(str_buf, fp);
-       SetDataDir(str_buf);
+       /* Release file */
+       FreeFile(fp);
+       if (unlink(id) != 0)
+       {
+               write_stderr("could not remove file \"%s\": %s\n",
+                                        id, strerror(errno));
+               exit(1);
+       }
+#else
+       /* Win32 version uses mapped file */
+       HANDLE paramHandle;
+       BackendParameters *paramp;
 
-       read_array_var(ListenSocket, fp);
+       paramHandle = (HANDLE)atol(id);
+       paramp = MapViewOfFile(paramHandle, FILE_MAP_READ, 0, 0, 0);
+       if (!paramp)
+       {
+               write_stderr("could not map view of backend variables: error code %d\n",
+                                        (int) GetLastError());
+               exit(1);
+       }
+
+       memcpy(&param, paramp, sizeof(BackendParameters));
+
+       if (!UnmapViewOfFile(paramp))
+       {
+               write_stderr("could not unmap view of backend variables: error code %d\n",
+                                        (int) GetLastError());
+               exit(1);
+       }
+
+       if (!CloseHandle(paramHandle))
+       {
+               write_stderr("could not close handle to backend parameter variables: error code %d\n",
+                                        (int) GetLastError());
+               exit(1);
+       }
+#endif
+
+       restore_backend_variables(&param, port);
+}
+
+/* Restore critical backend variables from the BackendParameters struct */
+static void
+restore_backend_variables(BackendParameters *param, Port *port)
+{
+       memcpy(port, &param->port, sizeof(Port));
+       read_inheritable_socket(&port->sock, &param->portsocket);
 
-       read_var(MyCancelKey, fp);
+       SetDataDir(param->DataDir);
 
-       read_var(UsedShmemSegID, fp);
-       read_var(UsedShmemSegAddr, fp);
+       memcpy(&ListenSocket, &param->ListenSocket, sizeof(ListenSocket));
 
-       read_var(ShmemLock, fp);
-       read_var(ShmemIndexLock, fp);
-       read_var(ShmemVariableCache, fp);
-       read_var(ShmemIndexAlloc, fp);
-       read_var(ShmemBackendArray, fp);
+       MyCancelKey = param->MyCancelKey;
 
-       read_var(LWLockArray, fp);
-       read_var(ProcStructLock, fp);
-       read_var(pgStatSock, fp);
+       UsedShmemSegID = param->UsedShmemSegID;
+       UsedShmemSegAddr = param->UsedShmemSegAddr;
+
+       ShmemLock = param->ShmemLock;
+       ShmemIndexLock = param->ShmemIndexLock;
+       ShmemVariableCache = param->ShmemVariableCache;
+       ShmemIndexAlloc = param->ShmemIndexAlloc;
+       ShmemBackendArray = param->ShmemBackendArray;
+
+       LWLockArray = param->LWLockArray;
+       ProcStructLock = param->ProcStructLock;
+       read_inheritable_socket(&pgStatSock, &param->pgStatSock);
+       read_inheritable_socket(&pgStatPipe[0], &param->pgStatPipe0);
+       read_inheritable_socket(&pgStatPipe[1], &param->pgStatPipe1);
+
+       PostmasterPid = param->PostmasterPid;
 
-       read_var(debug_flag, fp);
-       read_var(PostmasterPid, fp);
 #ifdef WIN32
-       read_var(PostmasterHandle, fp);
+       PostmasterHandle = param->PostmasterHandle;
+       pgwin32_initial_signal_pipe = param->initial_signal_pipe;
 #endif
 
-       read_var(syslogPipe[0], fp);
-       read_var(syslogPipe[1], fp);
-
-       read_array_var(str_buf, fp);
-       StrNCpy(my_exec_path, str_buf, MAXPGPATH);
+       memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
 
-       read_array_var(ExtraOptions, fp);
+       StrNCpy(my_exec_path, param->my_exec_path, MAXPGPATH);
 
-       read_array_var(str_buf, fp);
-       setlocale(LC_COLLATE, str_buf);
-       read_array_var(str_buf, fp);
-       setlocale(LC_CTYPE, str_buf);
+       StrNCpy(ExtraOptions, param->ExtraOptions, MAXPGPATH);
 
-       /* Release file */
-       FreeFile(fp);
-       if (unlink(filename) != 0)
-               ereport(WARNING,
-                               (errcode_for_file_access(),
-                                errmsg("could not remove file \"%s\": %m", filename)));
+       setlocale(LC_COLLATE, param->lc_collate);
+       setlocale(LC_CTYPE, param->lc_ctype);
 }
 
 
@@ -3607,79 +3951,11 @@ ShmemBackendArrayRemove(pid_t pid)
                                                         (int) pid)));
 }
 
-#endif /* EXEC_BACKEND */
+#endif   /* EXEC_BACKEND */
 
 
 #ifdef WIN32
 
-static pid_t
-win32_forkexec(const char *path, char *argv[])
-{
-       STARTUPINFO si;
-       PROCESS_INFORMATION pi;
-       int                     i;
-       int                     j;
-       char            cmdLine[MAXPGPATH * 2];
-       HANDLE          childHandleCopy;
-       HANDLE          waiterThread;
-
-       /* Format the cmd line */
-       cmdLine[sizeof(cmdLine)-1] = '\0';
-       cmdLine[sizeof(cmdLine)-2] = '\0';
-       snprintf(cmdLine, sizeof(cmdLine)-1, "\"%s\"", path);
-       i = 0;
-       while (argv[++i] != NULL)
-       {
-               j = strlen(cmdLine);
-               snprintf(cmdLine+j, sizeof(cmdLine)-1-j, " \"%s\"", argv[i]);
-       }
-       if (cmdLine[sizeof(cmdLine)-2] != '\0')
-       {
-               elog(LOG, "subprocess command line too long");
-               return -1;
-       }
-
-       memset(&pi, 0, sizeof(pi));
-       memset(&si, 0, sizeof(si));
-       si.cb = sizeof(si);
-       if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
-       {
-               elog(LOG, "CreateProcess call failed (%d): %m", (int) GetLastError());
-               return -1;
-       }
-
-       if (!IsUnderPostmaster)
-       {
-               /* We are the Postmaster creating a child... */
-               win32_AddChild(pi.dwProcessId, pi.hProcess);
-       }
-
-       if (DuplicateHandle(GetCurrentProcess(),
-                                               pi.hProcess,
-                                               GetCurrentProcess(),
-                                               &childHandleCopy,
-                                               0,
-                                               FALSE,
-                                               DUPLICATE_SAME_ACCESS) == 0)
-               ereport(FATAL,
-                               (errmsg_internal("could not duplicate child handle: %d",
-                                                                (int) GetLastError())));
-
-       waiterThread = CreateThread(NULL, 64 * 1024, win32_sigchld_waiter,
-                                                               (LPVOID) childHandleCopy, 0, NULL);
-       if (!waiterThread)
-               ereport(FATAL,
-                               (errmsg_internal("could not create sigchld waiter thread: %d",
-                                                                (int) GetLastError())));
-       CloseHandle(waiterThread);
-
-       if (IsUnderPostmaster)
-               CloseHandle(pi.hProcess);
-       CloseHandle(pi.hThread);
-
-       return pi.dwProcessId;
-}
-
 /*
  * Note: The following three functions must not be interrupted (eg. by
  * signals).  As the Postgres Win32 signalling architecture (currently)
@@ -3736,13 +4012,13 @@ win32_RemoveChild(pid_t pid)
 static pid_t
 win32_waitpid(int *exitstatus)
 {
-               /*
-                * Note: Do NOT use WaitForMultipleObjectsEx, as we don't want to
-                * run queued APCs here.
-                */
-               int                     index;
-               DWORD           exitCode;
-               DWORD           ret;
+       /*
+        * Note: Do NOT use WaitForMultipleObjectsEx, as we don't want to run
+        * queued APCs here.
+        */
+       int                     index;
+       DWORD           exitCode;
+       DWORD           ret;
        unsigned long offset;
 
        Assert(win32_childPIDArray && win32_childHNDArray);
@@ -3750,14 +4026,15 @@ win32_waitpid(int *exitstatus)
 
        for (offset = 0; offset < win32_numChildren; offset += MAXIMUM_WAIT_OBJECTS)
        {
-               unsigned long num = min(MAXIMUM_WAIT_OBJECTS, win32_numChildren - offset);
+               unsigned long num = Min(MAXIMUM_WAIT_OBJECTS, win32_numChildren - offset);
+
                ret = WaitForMultipleObjects(num, &win32_childHNDArray[offset], FALSE, 0);
                switch (ret)
                {
                        case WAIT_FAILED:
                                ereport(LOG,
-                                               (errmsg_internal("failed to wait on %lu of %lu children: %d",
-                                                                                num, win32_numChildren, (int) GetLastError())));
+                                               (errmsg_internal("failed to wait on %lu of %lu children: error code %d",
+                                                num, win32_numChildren, (int) GetLastError())));
                                return -1;
 
                        case WAIT_TIMEOUT:
@@ -3765,6 +4042,7 @@ win32_waitpid(int *exitstatus)
                                break;
 
                        default:
+
                                /*
                                 * Get the exit code, and return the PID of, the
                                 * respective process
@@ -3780,7 +4058,7 @@ win32_waitpid(int *exitstatus)
                                         */
                                        ereport(FATAL,
                                                        (errmsg_internal("failed to get exit code for child %lu",
-                                                                                  win32_childPIDArray[index])));
+                                                                                        (unsigned long) win32_childPIDArray[index])));
                                }
                                *exitstatus = (int) exitCode;
                                return win32_childPIDArray[index];
@@ -3805,10 +4083,10 @@ win32_sigchld_waiter(LPVOID param)
        if (r == WAIT_OBJECT_0)
                pg_queue_signal(SIGCHLD);
        else
-               write_stderr("ERROR: failed to wait on child process handle: %d\n",
-                               (int) GetLastError());
+               write_stderr("could not wait on child process handle: error code %d\n",
+                                        (int) GetLastError());
        CloseHandle(procHandle);
        return 0;
 }
 
-#endif /* WIN32 */
+#endif   /* WIN32 */