aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_ctl/pg_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_ctl/pg_ctl.c')
-rw-r--r--src/bin/pg_ctl/pg_ctl.c185
1 files changed, 93 insertions, 92 deletions
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 03a932970d1..6c87f158f3f 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -22,7 +22,6 @@
#include <locale.h>
#include <signal.h>
-#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -91,6 +90,24 @@ static char *register_username = NULL;
static char *register_password = NULL;
static char *argv0 = NULL;
static bool allow_core_files = false;
+static time_t start_time;
+
+static char postopts_file[MAXPGPATH];
+static char pid_file[MAXPGPATH];
+static char backup_file[MAXPGPATH];
+static char recovery_file[MAXPGPATH];
+
+#if defined(WIN32) || defined(__CYGWIN__)
+static DWORD pgctl_start_type = SERVICE_AUTO_START;
+static SERVICE_STATUS status;
+static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
+static HANDLE shutdownHandles[2];
+static pid_t postmasterPID = -1;
+
+#define shutdownEvent shutdownHandles[0]
+#define postmasterProcess shutdownHandles[1]
+#endif
+
static void
write_stderr(const char *fmt,...)
@@ -122,15 +139,6 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
static void pgwin32_doRunAsService(void);
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service);
-
-static DWORD pgctl_start_type = SERVICE_AUTO_START;
-static SERVICE_STATUS status;
-static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
-static HANDLE shutdownHandles[2];
-static pid_t postmasterPID = -1;
-
-#define shutdownEvent shutdownHandles[0]
-#define postmasterProcess shutdownHandles[1]
#endif
static pgpid_t get_pgpid(void);
@@ -140,12 +148,6 @@ static void read_post_opts(void);
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];
-static char backup_file[MAXPGPATH];
-static char recovery_file[MAXPGPATH];
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
static void unlimit_core_size(void);
@@ -406,14 +408,10 @@ start_postmaster(void)
static PGPing
test_postmaster_connection(bool do_checkpoint)
{
- int portnum = 0;
- char host_str[MAXPGPATH];
- char connstr[MAXPGPATH + 256];
PGPing ret = PQPING_OK; /* assume success for wait == zero */
- char **optlines;
+ char connstr[MAXPGPATH * 2 + 256];
int i;
- host_str[0] = '\0';
connstr[0] = '\0';
for (i = 0; i < wait_seconds; i++)
@@ -421,108 +419,111 @@ test_postmaster_connection(bool do_checkpoint)
/* Do we need a connection string? */
if (connstr[0] == '\0')
{
- /*
- * The number of lines in postmaster.pid tells us several things:
+ /*----------
+ * The number of lines in postmaster.pid tells us several things:
*
- * # of lines
+ * # 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, listen host not created
+ * 5 9.1+ server, ports not opened
* 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 connection
- * information in the file for us to use.
- * (PG_VERSION could also have told us the major version.)
+ * 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.
+ *----------
*/
-
- /* Try to read a completed postmaster.pid file */
+ char **optlines;
+
+ /* Try to read the postmaster.pid file */
if ((optlines = readfile(pid_file)) != NULL &&
optlines[0] != NULL &&
optlines[1] != NULL &&
- optlines[2] != NULL &&
- /* pre-9.1 server or listen_address line is present? */
- (optlines[3] == NULL ||
- optlines[5] != NULL))
- {
- /* A 3-line file? */
+ optlines[2] != NULL)
+ {
if (optlines[3] == NULL)
{
- /*
- * Pre-9.1: on Unix, we get the port number by
- * deriving it from the shmem key (the first number on
- * on the line); see
- * miscinit.c::RecordSharedMemoryInLockFile().
- */
- portnum = atoi(optlines[2]) / 1000;
- /* Win32 does not give us a shmem key, so we fail. */
- if (portnum == 0)
- {
- write_stderr(_("%s: -w option is not supported on this platform\nwhen connecting to a pre-9.1 server\n"),
- progname);
- return PQPING_NO_ATTEMPT;
- }
+ /* File is exactly three lines, must be pre-9.1 */
+ write_stderr(_("%s: -w option is not supported when starting a pre-9.1 server\n"),
+ progname);
+ return PQPING_NO_ATTEMPT;
}
- else
+ else if (optlines[4] != NULL &&
+ optlines[5] != NULL)
{
+ /* File is complete enough for us, parse it */
+ time_t pmstart;
+ int portnum;
+ char *sockdir;
+ char *hostaddr;
+ char host_str[MAXPGPATH];
+
/*
- * 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.
+ * Easy cross-check that we are looking at the right data
+ * directory: is the postmaster older than this execution
+ * of pg_ctl? Subtract 2 seconds to allow for possible
+ * clock skew between pg_ctl and the postmaster.
*/
- if (atol(optlines[1]) < start_time - 2)
+ pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
+ if (pmstart < start_time - 2)
{
- write_stderr(_("%s: this data directory is running an older postmaster\n"),
+ write_stderr(_("%s: this data directory is running a pre-existing 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.
+ * OK, 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_directory can accept relative
- * directories, libpq's host must have a leading slash
- * to indicate a socket directory.
+ * While unix_socket_directory 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 (optlines[4][0] != '\n' && optlines[4][0] != '/')
+ 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 we couldn't get either sockdir or host addr */
+ if (host_str[0] == '\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 (host_str[0] != '\0')
- snprintf(connstr + strlen(connstr), sizeof(connstr) - strlen(connstr),
- " host='%s'", host_str);
+ /* If postmaster is listening on "*", use "localhost" */
+ if (strcmp(host_str, "*") == 0)
+ strcpy(host_str, "localhost");
+
+ /*
+ * 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);
+ }
}
}
@@ -544,7 +545,7 @@ test_postmaster_connection(bool do_checkpoint)
* startup time is changing, otherwise it'll usually send a
* stop signal after 20 seconds, despite incrementing the
* checkpoint counter.
- */
+ */
status.dwWaitHint += 6000;
status.dwCheckPoint++;
SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);