<row>
  <entry><filename>postmaster.pid</></entry>
  <entry>A lock file recording the current postmaster process id (PID),
- cluster data directory, port number, Unix domain socket directory,
- and shared memory segment ID</entry>
+ postmaster start time, cluster data directory, port number, user-specified
+ Unix domain socket directory, first valid listen_address host, and
+ shared memory segment ID</entry>
 </row>
 
 </tbody>
 
 }
 
 void
-RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
+AddToLockFile(int target_line, const char *str)
 {
 }
 
 
    /* Register on-exit routine to detach new segment before deleting */
    on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));
 
-   /* Record key and ID in lockfile for data directory. */
-   RecordSharedMemoryInLockFile((unsigned long) memKey,
-                                (unsigned long) shmid);
+   /*
+    * Append record key and ID in lockfile for data directory. Format
+    * to try to keep it the same length.
+    */
+   {
+       char line[32];
+
+       sprintf(line, "%9lu %9lu\n", (unsigned long) memKey,
+                                    (unsigned long) shmid);
+       AddToLockFile(LOCK_FILE_LINES, line);
+   }
 
    return memAddress;
 }
 
    int         status;
    char       *userDoption = NULL;
    int         i;
-
+   bool        connection_line_output = false;
+   
    MyProcPid = PostmasterPid = getpid();
 
    MyStartTime = time(NULL);
                                          UnixSocketDir,
                                          ListenSocket, MAXLISTEN);
            else
+           {
                status = StreamServerPort(AF_UNSPEC, curhost,
                                          (unsigned short) PostPortNumber,
                                          UnixSocketDir,
                                          ListenSocket, MAXLISTEN);
+               /* must supply a valid listen_address for PQping() */
+               if (!connection_line_output)
+               {
+                   char line[MAXPGPATH + 2];
+
+                   sprintf(line, "%s\n", curhost);
+                   AddToLockFile(LOCK_FILE_LINES - 1, line);
+                   connection_line_output = true;
+               }
+           }
+               
            if (status == STATUS_OK)
                success++;
            else
        pfree(rawstring);
    }
 
+   /* Supply an empty listen_address line for PQping() */
+   if (!connection_line_output)
+       AddToLockFile(LOCK_FILE_LINES - 1, "\n");
+
 #ifdef USE_BONJOUR
    /* Register for Bonjour only if we opened TCP socket(s) */
    if (enable_bonjour && ListenSocket[0] != PGINVALID_SOCKET)
 
 
 
 #define DIRECTORY_LOCK_FILE        "postmaster.pid"
-
+/*
+ * The lock file contents are:
+ *
+ * line #
+ *     1   pid
+ *     2   postmaster start time
+ *     3   data directory
+ *     4   port #
+ *     5   user-specified socket directory
+ *         (the lines below are added later)
+ *     6   first valid listen_address
+ *     7   shared memory key
+ */
+   
 ProcessingMode Mode = InitProcessing;
 
 /* Note: we rely on this to initialize as zeroes */
               bool isDDLock, const char *refName)
 {
    int         fd;
-   char        buffer[MAXPGPATH * 2 + 256];
+   char        buffer[MAXPGPATH * 3 + 256];
    int         ntries;
    int         len;
    int         encoded_pid;
        if (isDDLock)
        {
            char       *ptr = buffer;
-           unsigned long id1,
-                       id2;
+           unsigned long id1, id2;
            int lineno;
 
-           for (lineno = 1; lineno <= 4; lineno++)
+           for (lineno = 1; lineno <= LOCK_FILE_LINES - 1; lineno++)
            {
                if ((ptr = strchr(ptr, '\n')) == NULL)
                {
    /*
     * Successfully created the file, now fill it.
     */
-   snprintf(buffer, sizeof(buffer), "%d\n%s\n%d\n%s\n",
+   snprintf(buffer, sizeof(buffer), "%d\n%ld\n%s\n%d\n%s\n",
             amPostmaster ? (int) my_pid : -((int) my_pid),
-            DataDir, PostPortNumber, UnixSocketDir);
+            (long) MyStartTime, DataDir, PostPortNumber,
+            UnixSocketDir);
    errno = 0;
    if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
    {
    }
 }
 
+
 /*
- * Append information about a shared memory segment to the data directory
- * lock file.
- *
- * This may be called multiple times in the life of a postmaster, if we
- * delete and recreate shmem due to backend crash. Therefore, be prepared
- * to overwrite existing information.  (As of 7.1, a postmaster only creates
- * one shm seg at a time; but for the purposes here, if we did have more than
- * one then any one of them would do anyway.)
+ * Add lines to the data directory lock file.  This erases all following
+ * lines, but that is OK because lines are added in order.
  */
 void
-RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
+AddToLockFile(int target_line, const char *str)
 {
    int         fd;
    int         len;
    int         lineno;
    char       *ptr;
-   char        buffer[MAXPGPATH * 2 + 256];
+   char        buffer[MAXPGPATH * 3 + 256];
 
    fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
    if (fd < 0)
     * Skip over first four lines (PID, pgdata, portnum, socketdir).
     */
    ptr = buffer;
-   for (lineno = 1; lineno <= 4; lineno++)
+   for (lineno = 1; lineno < target_line; lineno++)
    {
        if ((ptr = strchr(ptr, '\n')) == NULL)
        {
        ptr++;
    }
    
-   /*
-    * Append key information.  Format to try to keep it the same length
-    * always (trailing junk won't hurt, but might confuse humans).
-    */
-   sprintf(ptr, "%9lu %9lu\n", id1, id2);
+   strlcat(buffer, str, sizeof(buffer));
 
    /*
     * And rewrite the data.  Since we write in a single kernel call, this
 
 
 #include <locale.h>
 #include <signal.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
 static PGPing test_postmaster_connection(bool);
 static bool postmaster_is_alive(pid_t pid);
+static time_t start_time;
 
 static char postopts_file[MAXPGPATH];
 static char pid_file[MAXPGPATH];
 test_postmaster_connection(bool do_checkpoint)
 {
    int         portnum = 0;
-   char        socket_dir[MAXPGPATH];
+   char        host_str[MAXPGPATH];
    char        connstr[MAXPGPATH + 256];
    PGPing      ret = PQPING_OK;    /* assume success for wait == zero */
    char      **optlines;
    int         i;
 
-   socket_dir[0] = '\0';
+   host_str[0] = '\0';
    connstr[0] = '\0';
    
    for (i = 0; i < wait_seconds; i++)
             *      0   lock file created but status not written
             *      2   pre-9.1 server, shared memory not created
             *      3   pre-9.1 server, shared memory created
-            *      4   9.1+ server, shared memory not created
-            *      5   9.1+ server, shared memory created
+            *      5   9.1+ server, listen host not created
+            *      6   9.1+ server, shared memory not created
+            *      7   9.1+ server, shared memory created
             *
             *  For pre-9.1 Unix servers, we grab the port number from the
             *  shmem key (first value on line 3).  Pre-9.1 Win32 has no
-            *  written shmem key, so we fail.  9.1+ writes both the port
-            *  number and socket address in the file for us to use.
+            *  written shmem key, so we fail.  9.1+ writes connection
+            *  information in the file for us to use.
             *  (PG_VERSION could also have told us the major version.)
             */
        
            if ((optlines = readfile(pid_file)) != NULL &&
                optlines[0] != NULL &&
                optlines[1] != NULL &&
-               optlines[2] != NULL)
+               optlines[2] != NULL &&
+               /* pre-9.1 server or listen_address line is present? */
+               (optlines[3] == NULL ||
+                optlines[5] != NULL))
            {               
                /* A 3-line file? */
                if (optlines[3] == NULL)
                        return PQPING_NO_ATTEMPT;
                    }
                }
-               else    /* 9.1+ server */
+               else
                {
-                   portnum = atoi(optlines[2]);
-   
-                   /* Get socket directory, if specified. */
-                   if (optlines[3][0] != '\n')
+                   /*
+                    *  Easy check to see if we are looking at the right
+                    *  data directory:  Is the postmaster older than this
+                    *  execution of pg_ctl?  Subtract 2 seconds to account
+                    *  for possible clock skew between pg_ctl and the
+                    *  postmaster.
+                    */
+                   if (atol(optlines[1]) < start_time - 2)
                    {
-                       /*
-                        *  While unix_socket_directory can accept relative
-                        *  directories, libpq's host must have a leading slash
-                        *  to indicate a socket directory.
-                        */
-                       if (optlines[3][0] != '/')
-                       {
-                           write_stderr(_("%s: -w option cannot use a relative socket directory specification\n"),
-                                        progname);
-                           return PQPING_NO_ATTEMPT;
-                       }
-                       strlcpy(socket_dir, optlines[3], MAXPGPATH);
-                       /* remove newline */
-                       if (strchr(socket_dir, '\n') != NULL)
-                           *strchr(socket_dir, '\n') = '\0';
+                       write_stderr(_("%s: this data directory is running an older postmaster\n"),
+                                    progname);
+                       return PQPING_NO_ATTEMPT;
                    }
-               }
+                       
+                   portnum = atoi(optlines[3]);
 
+                   /*
+                    *  Determine the proper host string to use.
+                    */
+#ifdef HAVE_UNIX_SOCKETS
+                   /*
+                    *  Use socket directory, if specified.  We assume if we
+                    *  have unix sockets, the server does too because we
+                    *  just started the postmaster.
+                    */
+                   /*
+                    *  While unix_socket_directory can accept relative
+                    *  directories, libpq's host must have a leading slash
+                    *  to indicate a socket directory.
+                    */
+                   if (optlines[4][0] != '\n' && optlines[4][0] != '/')
+                   {
+                       write_stderr(_("%s: -w option cannot use a relative socket directory specification\n"),
+                                    progname);
+                       return PQPING_NO_ATTEMPT;
+                   }
+                   strlcpy(host_str, optlines[4], sizeof(host_str));
+#else
+                   strlcpy(host_str, optlines[5], sizeof(host_str));
+#endif
+                   /* remove newline */
+                   if (strchr(host_str, '\n') != NULL)
+                       *strchr(host_str, '\n') = '\0';
+               }
+               
                /*
                 * We need to set connect_timeout otherwise on Windows the
                 * Service Control Manager (SCM) will probably timeout first.
                snprintf(connstr, sizeof(connstr),
                         "dbname=postgres port=%d connect_timeout=5", portnum);
 
-               if (socket_dir[0] != '\0')
+               if (host_str[0] != '\0')
                    snprintf(connstr + strlen(connstr), sizeof(connstr) - strlen(connstr),
-                       " host='%s'", socket_dir);
+                       " host='%s'", host_str);
            }
        }
 
 
    progname = get_progname(argv[0]);
    set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));
+   start_time = time(NULL);
 
    /*
     * save argv[0] so do_start() can look for the postmaster if necessary. we
 
 extern char *shared_preload_libraries_string;
 extern char *local_preload_libraries_string;
 
+#define LOCK_FILE_LINES        7
 extern void CreateDataDirLockFile(bool amPostmaster);
 extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster);
 extern void TouchSocketLockFile(void);
-extern void RecordSharedMemoryInLockFile(unsigned long id1,
-                            unsigned long id2);
+extern void AddToLockFile(int target_line, const char *str);
 extern void ValidatePgVersion(const char *path);
 extern void process_shared_preload_libraries(void);
 extern void process_local_preload_libraries(void);