aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/main/main.c2
-rw-r--r--src/backend/port/sysv_shmem.c1
-rw-r--r--src/backend/postmaster/postmaster.c30
-rw-r--r--src/backend/utils/init/miscinit.c29
-rw-r--r--src/bin/pg_ctl/Makefile6
-rw-r--r--src/bin/pg_ctl/pg_ctl.c265
-rw-r--r--src/bin/pg_ctl/t/001_start_stop.pl8
-rw-r--r--src/bin/pg_upgrade/option.c2
-rw-r--r--src/common/config_info.c1
-rw-r--r--src/include/miscadmin.h27
-rw-r--r--src/include/port.h3
-rw-r--r--src/include/utils/pidfile.h55
-rw-r--r--src/tools/msvc/Mkvcbuild.pm2
13 files changed, 203 insertions, 228 deletions
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index 09f99486e01..87b7d3bf65c 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -169,7 +169,7 @@ main(int argc, char *argv[])
}
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
{
- puts("postgres (PostgreSQL) " PG_VERSION);
+ fputs(PG_BACKEND_VERSIONSTR, stdout);
exit(0);
}
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 273d1313b00..e8cf6d3e936 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -38,6 +38,7 @@
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
#include "utils/guc.h"
+#include "utils/pidfile.h"
/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 2874f635af3..5f4dd689410 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -125,6 +125,7 @@
#include "utils/datetime.h"
#include "utils/dynamic_loader.h"
#include "utils/memutils.h"
+#include "utils/pidfile.h"
#include "utils/ps_status.h"
#include "utils/timeout.h"
#include "utils/varlena.h"
@@ -1341,6 +1342,12 @@ PostmasterMain(int argc, char *argv[])
#endif
/*
+ * Report postmaster status in the postmaster.pid file, to allow pg_ctl to
+ * see what's happening.
+ */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STARTING);
+
+ /*
* We're ready to rock and roll...
*/
StartupPID = StartupDataBase();
@@ -2608,6 +2615,9 @@ pmdie(SIGNAL_ARGS)
Shutdown = SmartShutdown;
ereport(LOG,
(errmsg("received smart shutdown request")));
+
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STOPPING);
#ifdef USE_SYSTEMD
sd_notify(0, "STOPPING=1");
#endif
@@ -2663,6 +2673,9 @@ pmdie(SIGNAL_ARGS)
Shutdown = FastShutdown;
ereport(LOG,
(errmsg("received fast shutdown request")));
+
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STOPPING);
#ifdef USE_SYSTEMD
sd_notify(0, "STOPPING=1");
#endif
@@ -2727,6 +2740,9 @@ pmdie(SIGNAL_ARGS)
Shutdown = ImmediateShutdown;
ereport(LOG,
(errmsg("received immediate shutdown request")));
+
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STOPPING);
#ifdef USE_SYSTEMD
sd_notify(0, "STOPPING=1");
#endif
@@ -2872,6 +2888,8 @@ reaper(SIGNAL_ARGS)
ereport(LOG,
(errmsg("database system is ready to accept connections")));
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_READY);
#ifdef USE_SYSTEMD
sd_notify(0, "READY=1");
#endif
@@ -5005,10 +5023,18 @@ sigusr1_handler(SIGNAL_ARGS)
if (XLogArchivingAlways())
PgArchPID = pgarch_start();
-#ifdef USE_SYSTEMD
+ /*
+ * If we aren't planning to enter hot standby mode later, treat
+ * RECOVERY_STARTED as meaning we're out of startup, and report status
+ * accordingly.
+ */
if (!EnableHotStandby)
+ {
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STANDBY);
+#ifdef USE_SYSTEMD
sd_notify(0, "READY=1");
#endif
+ }
pmState = PM_RECOVERY;
}
@@ -5024,6 +5050,8 @@ sigusr1_handler(SIGNAL_ARGS)
ereport(LOG,
(errmsg("database system is ready to accept read only connections")));
+ /* Report status */
+ AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_READY);
#ifdef USE_SYSTEMD
sd_notify(0, "READY=1");
#endif
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 49a6afafe7f..afbf8f86919 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -47,6 +47,7 @@
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
+#include "utils/pidfile.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
@@ -1149,8 +1150,9 @@ TouchSocketLockFiles(void)
*
* Note: because we don't truncate the file, if we were to rewrite a line
* with less data than it had before, there would be garbage after the last
- * line. We don't ever actually do that, so not worth adding another kernel
- * call to cover the possibility.
+ * line. While we could fix that by adding a truncate call, that would make
+ * the file update non-atomic, which we'd rather avoid. Therefore, callers
+ * should endeavor never to shorten a line once it's been written.
*/
void
AddToDataDirLockFile(int target_line, const char *str)
@@ -1193,19 +1195,26 @@ AddToDataDirLockFile(int target_line, const char *str)
srcptr = srcbuffer;
for (lineno = 1; lineno < target_line; lineno++)
{
- if ((srcptr = strchr(srcptr, '\n')) == NULL)
- {
- elog(LOG, "incomplete data in \"%s\": found only %d newlines while trying to add line %d",
- DIRECTORY_LOCK_FILE, lineno - 1, target_line);
- close(fd);
- return;
- }
- srcptr++;
+ char *eol = strchr(srcptr, '\n');
+
+ if (eol == NULL)
+ break; /* not enough lines in file yet */
+ srcptr = eol + 1;
}
memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
destptr = destbuffer + (srcptr - srcbuffer);
/*
+ * Fill in any missing lines before the target line, in case lines are
+ * added to the file out of order.
+ */
+ for (; lineno < target_line; lineno++)
+ {
+ if (destptr < destbuffer + sizeof(destbuffer))
+ *destptr++ = '\n';
+ }
+
+ /*
* Write or rewrite the target line.
*/
snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
diff --git a/src/bin/pg_ctl/Makefile b/src/bin/pg_ctl/Makefile
index f5ec088c42f..46f30bd46f9 100644
--- a/src/bin/pg_ctl/Makefile
+++ b/src/bin/pg_ctl/Makefile
@@ -16,14 +16,12 @@ subdir = src/bin/pg_ctl
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
-
OBJS= pg_ctl.o $(WIN32RES)
all: pg_ctl
-pg_ctl: $(OBJS) | submake-libpq submake-libpgport
- $(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+pg_ctl: $(OBJS) | submake-libpgport
+ $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
install: all installdirs
$(INSTALL_PROGRAM) pg_ctl$(X) '$(DESTDIR)$(bindir)/pg_ctl$(X)'
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index ad2a16f7558..6f057902098 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -34,9 +34,7 @@
#include "catalog/pg_control.h"
#include "common/controldata_utils.h"
#include "getopt_long.h"
-#include "libpq-fe.h"
-#include "miscadmin.h"
-#include "pqexpbuffer.h"
+#include "utils/pidfile.h"
/* PID can be negative for standalone backend */
typedef long pgpid_t;
@@ -49,6 +47,12 @@ typedef enum
IMMEDIATE_MODE
} ShutdownMode;
+typedef enum
+{
+ POSTMASTER_READY,
+ POSTMASTER_STILL_STARTING,
+ POSTMASTER_FAILED
+} WaitPMResult;
typedef enum
{
@@ -147,12 +151,12 @@ static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo,
#endif
static pgpid_t get_pgpid(bool is_status_request);
-static char **readfile(const char *path);
+static char **readfile(const char *path, int *numlines);
static void free_readfile(char **optlines);
static pgpid_t start_postmaster(void);
static void read_post_opts(void);
-static PGPing test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint);
+static WaitPMResult wait_for_postmaster(pgpid_t pm_pid, bool do_checkpoint);
static bool postmaster_is_alive(pid_t pid);
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
@@ -304,9 +308,14 @@ get_pgpid(bool is_status_request)
/*
* get the lines from a text file - return NULL if file can't be opened
+ *
+ * Trailing newlines are deleted from the lines (this is a change from pre-v10)
+ *
+ * *numlines is set to the number of line pointers returned; there is
+ * also an additional NULL pointer after the last real line.
*/
static char **
-readfile(const char *path)
+readfile(const char *path, int *numlines)
{
int fd;
int nlines;
@@ -318,6 +327,8 @@ readfile(const char *path)
int len;
struct stat statbuf;
+ *numlines = 0; /* in case of failure or empty file */
+
/*
* Slurp the file into memory.
*
@@ -367,6 +378,7 @@ readfile(const char *path)
/* set up the result buffer */
result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
+ *numlines = nlines;
/* now split the buffer into lines */
linebegin = buffer;
@@ -375,10 +387,13 @@ readfile(const char *path)
{
if (buffer[i] == '\n')
{
- int slen = &buffer[i] - linebegin + 1;
+ int slen = &buffer[i] - linebegin;
char *linebuf = pg_malloc(slen + 1);
memcpy(linebuf, linebegin, slen);
+ /* we already dropped the \n, but get rid of any \r too */
+ if (slen > 0 && linebuf[slen - 1] == '\r')
+ slen--;
linebuf[slen] = '\0';
result[n++] = linebuf;
linebegin = &buffer[i + 1];
@@ -509,7 +524,7 @@ start_postmaster(void)
/*
- * Find the pgport and try a connection
+ * Wait for the postmaster to become ready.
*
* On Unix, pm_pid is the PID of the just-launched postmaster. On Windows,
* it may be the PID of an ancestor shell process, so we can't check the
@@ -522,168 +537,67 @@ start_postmaster(void)
* Note that the checkpoint parameter enables a Windows service control
* manager checkpoint, it's got nothing to do with database checkpoints!!
*/
-static PGPing
-test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint)
+static WaitPMResult
+wait_for_postmaster(pgpid_t pm_pid, bool do_checkpoint)
{
- PGPing ret = PQPING_NO_RESPONSE;
- char connstr[MAXPGPATH * 2 + 256];
int i;
- /* if requested wait time is zero, return "still starting up" code */
- if (wait_seconds <= 0)
- return PQPING_REJECT;
-
- connstr[0] = '\0';
-
for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++)
{
- /* Do we need a connection string? */
- if (connstr[0] == '\0')
+ char **optlines;
+ int numlines;
+
+ /*
+ * Try to read the postmaster.pid file. If it's not valid, or if the
+ * status line isn't there yet, just keep waiting.
+ */
+ if ((optlines = readfile(pid_file, &numlines)) != NULL &&
+ numlines >= LOCK_FILE_LINE_PM_STATUS)
{
- /*----------
- * The number of lines in postmaster.pid tells us several things:
- *
- * # of lines
- * 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
- * 5 9.1+ server, ports not opened
- * 6 9.1+ server, shared memory not created
- * 7 9.1+ server, shared memory created
- *
- * This code does not support pre-9.1 servers. On Unix machines
- * we could consider extracting the port number from the shmem
- * key, but that (a) is not robust, and (b) doesn't help with
- * finding out the socket directory. And it wouldn't work anyway
- * on Windows.
- *
- * If we see less than 6 lines in postmaster.pid, just keep
- * waiting.
- *----------
- */
- char **optlines;
+ /* File is complete enough for us, parse it */
+ pgpid_t pmpid;
+ time_t pmstart;
- /* Try to read the postmaster.pid file */
- if ((optlines = readfile(pid_file)) != NULL &&
- optlines[0] != NULL &&
- optlines[1] != NULL &&
- optlines[2] != NULL)
- {
- if (optlines[3] == NULL)
- {
- /* File is exactly three lines, must be pre-9.1 */
- write_stderr(_("\n%s: -w option is not supported when starting a pre-9.1 server\n"),
- progname);
- return PQPING_NO_ATTEMPT;
- }
- else if (optlines[4] != NULL &&
- optlines[5] != NULL)
- {
- /* File is complete enough for us, parse it */
- pgpid_t pmpid;
- time_t pmstart;
-
- /*
- * Make sanity checks. If it's for the wrong PID, or the
- * recorded start time is before pg_ctl started, then
- * either we are looking at the wrong data directory, or
- * this is a pre-existing pidfile that hasn't (yet?) been
- * overwritten by our child postmaster. Allow 2 seconds
- * slop for possible cross-process clock skew.
- */
- pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
- pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
- if (pmstart >= start_time - 2 &&
+ /*
+ * Make sanity checks. If it's for the wrong PID, or the recorded
+ * start time is before pg_ctl started, then either we are looking
+ * at the wrong data directory, or this is a pre-existing pidfile
+ * that hasn't (yet?) been overwritten by our child postmaster.
+ * Allow 2 seconds slop for possible cross-process clock skew.
+ */
+ pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
+ pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
+ if (pmstart >= start_time - 2 &&
#ifndef WIN32
- pmpid == pm_pid
+ pmpid == pm_pid
#else
- /* Windows can only reject standalone-backend PIDs */
- pmpid > 0
+ /* Windows can only reject standalone-backend PIDs */
+ pmpid > 0
#endif
- )
- {
- /*
- * OK, seems to be a valid pidfile from our child.
- */
- int portnum;
- char *sockdir;
- char *hostaddr;
- char host_str[MAXPGPATH];
-
- /*
- * Extract port number and host string to use. Prefer
- * using Unix socket if available.
- */
- portnum = atoi(optlines[LOCK_FILE_LINE_PORT - 1]);
- sockdir = optlines[LOCK_FILE_LINE_SOCKET_DIR - 1];
- hostaddr = optlines[LOCK_FILE_LINE_LISTEN_ADDR - 1];
-
- /*
- * While unix_socket_directories can accept relative
- * directories, libpq's host parameter must have a
- * leading slash to indicate a socket directory. So,
- * ignore sockdir if it's relative, and try to use TCP
- * instead.
- */
- if (sockdir[0] == '/')
- strlcpy(host_str, sockdir, sizeof(host_str));
- else
- strlcpy(host_str, hostaddr, sizeof(host_str));
-
- /* remove trailing newline */
- if (strchr(host_str, '\n') != NULL)
- *strchr(host_str, '\n') = '\0';
-
- /* Fail if couldn't get either sockdir or host addr */
- if (host_str[0] == '\0')
- {
- write_stderr(_("\n%s: -w option cannot use a relative socket directory specification\n"),
- progname);
- return PQPING_NO_ATTEMPT;
- }
-
- /*
- * Map listen-only addresses to counterparts usable
- * for establishing a connection. connect() to "::"
- * or "0.0.0.0" is not portable to OpenBSD 5.0 or to
- * Windows Server 2008, and connect() to "::" is
- * additionally not portable to NetBSD 6.0. (Cygwin
- * does handle both addresses, though.)
- */
- if (strcmp(host_str, "*") == 0)
- strcpy(host_str, "localhost");
- else if (strcmp(host_str, "0.0.0.0") == 0)
- strcpy(host_str, "127.0.0.1");
- else if (strcmp(host_str, "::") == 0)
- strcpy(host_str, "::1");
+ )
+ {
+ /*
+ * OK, seems to be a valid pidfile from our child. Check the
+ * status line (this assumes a v10 or later server).
+ */
+ char *pmstatus = optlines[LOCK_FILE_LINE_PM_STATUS - 1];
- /*
- * 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 host='%s' connect_timeout=5",
- portnum, host_str);
- }
+ if (strcmp(pmstatus, PM_STATUS_READY) == 0 ||
+ strcmp(pmstatus, PM_STATUS_STANDBY) == 0)
+ {
+ /* postmaster is done starting up */
+ free_readfile(optlines);
+ return POSTMASTER_READY;
}
}
-
- /*
- * Free the results of readfile.
- *
- * This is safe to call even if optlines is NULL.
- */
- free_readfile(optlines);
}
- /* If we have a connection string, ping the server */
- if (connstr[0] != '\0')
- {
- ret = PQping(connstr);
- if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT)
- break;
- }
+ /*
+ * Free the results of readfile.
+ *
+ * This is safe to call even if optlines is NULL.
+ */
+ free_readfile(optlines);
/*
* Check whether the child postmaster process is still alive. This
@@ -697,14 +611,14 @@ test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint)
int exitstatus;
if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
- return PQPING_NO_RESPONSE;
+ return POSTMASTER_FAILED;
}
#else
if (WaitForSingleObject(postmasterProcess, 0) == WAIT_OBJECT_0)
- return PQPING_NO_RESPONSE;
+ return POSTMASTER_FAILED;
#endif
- /* No response, or startup still in process; wait */
+ /* Startup still in process; wait, printing a dot once per second */
if (i % WAITS_PER_SEC == 0)
{
#ifdef WIN32
@@ -729,8 +643,8 @@ test_postmaster_connection(pgpid_t pm_pid, bool do_checkpoint)
pg_usleep(USEC_PER_SEC / WAITS_PER_SEC);
}
- /* return result of last call to PQping */
- return ret;
+ /* out of patience; report that postmaster is still starting up */
+ return POSTMASTER_STILL_STARTING;
}
@@ -764,14 +678,15 @@ read_post_opts(void)
if (ctl_command == RESTART_COMMAND)
{
char **optlines;
+ int numlines;
- optlines = readfile(postopts_file);
+ optlines = readfile(postopts_file, &numlines);
if (optlines == NULL)
{
write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
exit(1);
}
- else if (optlines[0] == NULL || optlines[1] != NULL)
+ else if (numlines != 1)
{
write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
progname, postopts_file);
@@ -779,14 +694,10 @@ read_post_opts(void)
}
else
{
- int len;
char *optline;
char *arg1;
optline = optlines[0];
- /* trim off line endings */
- len = strcspn(optline, "\r\n");
- optline[len] = '\0';
/*
* Are we at the first option, as defined by space and
@@ -917,28 +828,23 @@ do_start(void)
{
print_msg(_("waiting for server to start..."));
- switch (test_postmaster_connection(pm_pid, false))
+ switch (wait_for_postmaster(pm_pid, false))
{
- case PQPING_OK:
+ case POSTMASTER_READY:
print_msg(_(" done\n"));
print_msg(_("server started\n"));
break;
- case PQPING_REJECT:
+ case POSTMASTER_STILL_STARTING:
print_msg(_(" stopped waiting\n"));
print_msg(_("server is still starting up\n"));
break;
- case PQPING_NO_RESPONSE:
+ case POSTMASTER_FAILED:
print_msg(_(" stopped waiting\n"));
write_stderr(_("%s: could not start server\n"
"Examine the log output.\n"),
progname);
exit(1);
break;
- case PQPING_NO_ATTEMPT:
- print_msg(_(" failed\n"));
- write_stderr(_("%s: could not wait for server because of misconfiguration\n"),
- progname);
- exit(1);
}
}
else
@@ -1319,15 +1225,16 @@ do_status(void)
{
char **optlines;
char **curr_line;
+ int numlines;
printf(_("%s: server is running (PID: %ld)\n"),
progname, pid);
- optlines = readfile(postopts_file);
+ optlines = readfile(postopts_file, &numlines);
if (optlines != NULL)
{
for (curr_line = optlines; *curr_line != NULL; curr_line++)
- fputs(*curr_line, stdout);
+ puts(*curr_line);
/* Free the results of readfile */
free_readfile(optlines);
@@ -1634,7 +1541,7 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
if (do_wait)
{
write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
- if (test_postmaster_connection(postmasterPID, true) != PQPING_OK)
+ if (wait_for_postmaster(postmasterPID, true) != POSTMASTER_READY)
{
write_eventlog(EVENTLOG_ERROR_TYPE, _("Timed out waiting for server startup\n"));
pgwin32_SetServiceStatus(SERVICE_STOPPED);
@@ -1655,7 +1562,7 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
{
/*
* status.dwCheckPoint can be incremented by
- * test_postmaster_connection(), so it might not start from 0.
+ * wait_for_postmaster(), so it might not start from 0.
*/
int maxShutdownCheckPoint = status.dwCheckPoint + 12;
diff --git a/src/bin/pg_ctl/t/001_start_stop.pl b/src/bin/pg_ctl/t/001_start_stop.pl
index df6158bd1f2..9c3551f1a5b 100644
--- a/src/bin/pg_ctl/t/001_start_stop.pl
+++ b/src/bin/pg_ctl/t/001_start_stop.pl
@@ -4,7 +4,7 @@ use warnings;
use Config;
use PostgresNode;
use TestLib;
-use Test::More tests => 17;
+use Test::More tests => 19;
my $tempdir = TestLib::tempdir;
my $tempdir_short = TestLib::tempdir_short;
@@ -32,12 +32,14 @@ else
print $conf "listen_addresses = '127.0.0.1'\n";
}
close $conf;
-command_ok([ 'pg_ctl', 'start', '-D', "$tempdir/data" ], 'pg_ctl start');
+command_like([ 'pg_ctl', 'start', '-D', "$tempdir/data",
+ '-l', "$TestLib::log_path/001_start_stop_server.log" ],
+ qr/done.*server started/s, 'pg_ctl start');
# sleep here is because Windows builds can't check postmaster.pid exactly,
# so they may mistake a pre-existing postmaster.pid for one created by the
# postmaster they start. Waiting more than the 2 seconds slop time allowed
-# by test_postmaster_connection prevents that mistake.
+# by wait_for_postmaster() prevents that mistake.
sleep 3 if ($windows_os);
command_fails([ 'pg_ctl', 'start', '-D', "$tempdir/data" ],
'second pg_ctl start fails');
diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c
index de5bfddf5cd..cb77665cdab 100644
--- a/src/bin/pg_upgrade/option.c
+++ b/src/bin/pg_upgrade/option.c
@@ -14,8 +14,8 @@
#include <io.h>
#endif
-#include "miscadmin.h"
#include "getopt_long.h"
+#include "utils/pidfile.h"
#include "pg_upgrade.h"
diff --git a/src/common/config_info.c b/src/common/config_info.c
index ad506be9caf..e0841a5af2a 100644
--- a/src/common/config_info.c
+++ b/src/common/config_info.c
@@ -21,7 +21,6 @@
#endif
#include "common/config_info.h"
-#include "miscadmin.h"
/*
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 21a77289f86..dad98de98d7 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -28,8 +28,6 @@
#include "pgtime.h" /* for pg_time_t */
-#define PG_BACKEND_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
-
#define InvalidPid (-1)
@@ -431,31 +429,6 @@ extern char *session_preload_libraries_string;
extern char *shared_preload_libraries_string;
extern char *local_preload_libraries_string;
-/*
- * As of 9.1, the contents of the data-directory lock file are:
- *
- * line #
- * 1 postmaster PID (or negative of a standalone backend's PID)
- * 2 data directory path
- * 3 postmaster start timestamp (time_t representation)
- * 4 port number
- * 5 first Unix socket directory path (empty if none)
- * 6 first listen_address (IP address or "*"; empty if no TCP port)
- * 7 shared memory key (not present on Windows)
- *
- * Lines 6 and up are added via AddToDataDirLockFile() after initial file
- * creation.
- *
- * The socket lock file, if used, has the same contents as lines 1-5.
- */
-#define LOCK_FILE_LINE_PID 1
-#define LOCK_FILE_LINE_DATA_DIR 2
-#define LOCK_FILE_LINE_START_TIME 3
-#define LOCK_FILE_LINE_PORT 4
-#define LOCK_FILE_LINE_SOCKET_DIR 5
-#define LOCK_FILE_LINE_LISTEN_ADDR 6
-#define LOCK_FILE_LINE_SHMEM_KEY 7
-
extern void CreateDataDirLockFile(bool amPostmaster);
extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster,
const char *socketDir);
diff --git a/src/include/port.h b/src/include/port.h
index c2462167e4c..b1ba645655f 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -98,6 +98,9 @@ extern int find_my_exec(const char *argv0, char *retpath);
extern int find_other_exec(const char *argv0, const char *target,
const char *versionstr, char *retpath);
+/* Doesn't belong here, but this is used with find_other_exec(), so... */
+#define PG_BACKEND_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
+
/* Windows security token manipulation (in exec.c) */
#ifdef WIN32
extern BOOL AddUserToTokenDacl(HANDLE hToken);
diff --git a/src/include/utils/pidfile.h b/src/include/utils/pidfile.h
new file mode 100644
index 00000000000..c3db4c46e39
--- /dev/null
+++ b/src/include/utils/pidfile.h
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * pidfile.h
+ * Declarations describing the data directory lock file (postmaster.pid)
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/pidfile.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UTILS_PIDFILE_H
+#define UTILS_PIDFILE_H
+
+/*
+ * As of Postgres 10, the contents of the data-directory lock file are:
+ *
+ * line #
+ * 1 postmaster PID (or negative of a standalone backend's PID)
+ * 2 data directory path
+ * 3 postmaster start timestamp (time_t representation)
+ * 4 port number
+ * 5 first Unix socket directory path (empty if none)
+ * 6 first listen_address (IP address or "*"; empty if no TCP port)
+ * 7 shared memory key (empty on Windows)
+ * 8 postmaster status (see values below)
+ *
+ * Lines 6 and up are added via AddToDataDirLockFile() after initial file
+ * creation; also, line 5 is initially empty and is changed after the first
+ * Unix socket is opened.
+ *
+ * Socket lock file(s), if used, have the same contents as lines 1-5, with
+ * line 5 being their own directory.
+ */
+#define LOCK_FILE_LINE_PID 1
+#define LOCK_FILE_LINE_DATA_DIR 2
+#define LOCK_FILE_LINE_START_TIME 3
+#define LOCK_FILE_LINE_PORT 4
+#define LOCK_FILE_LINE_SOCKET_DIR 5
+#define LOCK_FILE_LINE_LISTEN_ADDR 6
+#define LOCK_FILE_LINE_SHMEM_KEY 7
+#define LOCK_FILE_LINE_PM_STATUS 8
+
+/*
+ * The PM_STATUS line may contain one of these values. All these strings
+ * must be the same length, per comments for AddToDataDirLockFile().
+ * We pad with spaces as needed to make that true.
+ */
+#define PM_STATUS_STARTING "starting" /* still starting up */
+#define PM_STATUS_STOPPING "stopping" /* in shutdown sequence */
+#define PM_STATUS_READY "ready " /* ready for connections */
+#define PM_STATUS_STANDBY "standby " /* up, won't accept connections */
+
+#endif /* UTILS_PIDFILE_H */
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 621238417d5..01798443497 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -49,7 +49,7 @@ my @contrib_excludes = (
# Set of variables for frontend modules
my $frontend_defines = { 'initdb' => 'FRONTEND' };
-my @frontend_uselibpq = ('pg_ctl', 'pg_upgrade', 'pgbench', 'psql', 'initdb');
+my @frontend_uselibpq = ('pg_upgrade', 'pgbench', 'psql', 'initdb');
my @frontend_uselibpgport = (
'pg_archivecleanup', 'pg_test_fsync',
'pg_test_timing', 'pg_upgrade',