mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
Include the first valid listen address in pg_ctl to improve server start
"wait" detection and add postmaster start time to help determine if the postmaster is actually using the specified data directory.
This commit is contained in:
@ -117,8 +117,9 @@ last started with</entry>
|
|||||||
<row>
|
<row>
|
||||||
<entry><filename>postmaster.pid</></entry>
|
<entry><filename>postmaster.pid</></entry>
|
||||||
<entry>A lock file recording the current postmaster process id (PID),
|
<entry>A lock file recording the current postmaster process id (PID),
|
||||||
cluster data directory, port number, Unix domain socket directory,
|
postmaster start time, cluster data directory, port number, user-specified
|
||||||
and shared memory segment ID</entry>
|
Unix domain socket directory, first valid listen_address host, and
|
||||||
|
shared memory segment ID</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -104,7 +104,7 @@ on_exit_reset(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
AddToLockFile(int target_line, const char *str)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,9 +198,17 @@ InternalIpcMemoryCreate(IpcMemoryKey memKey, Size size)
|
|||||||
/* Register on-exit routine to detach new segment before deleting */
|
/* Register on-exit routine to detach new segment before deleting */
|
||||||
on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));
|
on_shmem_exit(IpcMemoryDetach, PointerGetDatum(memAddress));
|
||||||
|
|
||||||
/* Record key and ID in lockfile for data directory. */
|
/*
|
||||||
RecordSharedMemoryInLockFile((unsigned long) memKey,
|
* 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);
|
(unsigned long) shmid);
|
||||||
|
AddToLockFile(LOCK_FILE_LINES, line);
|
||||||
|
}
|
||||||
|
|
||||||
return memAddress;
|
return memAddress;
|
||||||
}
|
}
|
||||||
|
@ -483,6 +483,7 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
int status;
|
int status;
|
||||||
char *userDoption = NULL;
|
char *userDoption = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
bool connection_line_output = false;
|
||||||
|
|
||||||
MyProcPid = PostmasterPid = getpid();
|
MyProcPid = PostmasterPid = getpid();
|
||||||
|
|
||||||
@ -860,10 +861,22 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
UnixSocketDir,
|
UnixSocketDir,
|
||||||
ListenSocket, MAXLISTEN);
|
ListenSocket, MAXLISTEN);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
status = StreamServerPort(AF_UNSPEC, curhost,
|
status = StreamServerPort(AF_UNSPEC, curhost,
|
||||||
(unsigned short) PostPortNumber,
|
(unsigned short) PostPortNumber,
|
||||||
UnixSocketDir,
|
UnixSocketDir,
|
||||||
ListenSocket, MAXLISTEN);
|
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)
|
if (status == STATUS_OK)
|
||||||
success++;
|
success++;
|
||||||
else
|
else
|
||||||
@ -880,6 +893,10 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
pfree(rawstring);
|
pfree(rawstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Supply an empty listen_address line for PQping() */
|
||||||
|
if (!connection_line_output)
|
||||||
|
AddToLockFile(LOCK_FILE_LINES - 1, "\n");
|
||||||
|
|
||||||
#ifdef USE_BONJOUR
|
#ifdef USE_BONJOUR
|
||||||
/* Register for Bonjour only if we opened TCP socket(s) */
|
/* Register for Bonjour only if we opened TCP socket(s) */
|
||||||
if (enable_bonjour && ListenSocket[0] != PGINVALID_SOCKET)
|
if (enable_bonjour && ListenSocket[0] != PGINVALID_SOCKET)
|
||||||
|
@ -46,6 +46,19 @@
|
|||||||
|
|
||||||
|
|
||||||
#define DIRECTORY_LOCK_FILE "postmaster.pid"
|
#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;
|
ProcessingMode Mode = InitProcessing;
|
||||||
|
|
||||||
@ -678,7 +691,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
|||||||
bool isDDLock, const char *refName)
|
bool isDDLock, const char *refName)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char buffer[MAXPGPATH * 2 + 256];
|
char buffer[MAXPGPATH * 3 + 256];
|
||||||
int ntries;
|
int ntries;
|
||||||
int len;
|
int len;
|
||||||
int encoded_pid;
|
int encoded_pid;
|
||||||
@ -845,11 +858,10 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
|||||||
if (isDDLock)
|
if (isDDLock)
|
||||||
{
|
{
|
||||||
char *ptr = buffer;
|
char *ptr = buffer;
|
||||||
unsigned long id1,
|
unsigned long id1, id2;
|
||||||
id2;
|
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
for (lineno = 1; lineno <= 4; lineno++)
|
for (lineno = 1; lineno <= LOCK_FILE_LINES - 1; lineno++)
|
||||||
{
|
{
|
||||||
if ((ptr = strchr(ptr, '\n')) == NULL)
|
if ((ptr = strchr(ptr, '\n')) == NULL)
|
||||||
{
|
{
|
||||||
@ -893,9 +905,10 @@ CreateLockFile(const char *filename, bool amPostmaster,
|
|||||||
/*
|
/*
|
||||||
* Successfully created the file, now fill it.
|
* 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),
|
amPostmaster ? (int) my_pid : -((int) my_pid),
|
||||||
DataDir, PostPortNumber, UnixSocketDir);
|
(long) MyStartTime, DataDir, PostPortNumber,
|
||||||
|
UnixSocketDir);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
|
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
|
||||||
{
|
{
|
||||||
@ -1004,24 +1017,19 @@ TouchSocketLockFile(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append information about a shared memory segment to the data directory
|
* Add lines to the data directory lock file. This erases all following
|
||||||
* lock file.
|
* lines, but that is OK because lines are added in order.
|
||||||
*
|
|
||||||
* 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.)
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
AddToLockFile(int target_line, const char *str)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int len;
|
int len;
|
||||||
int lineno;
|
int lineno;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
char buffer[MAXPGPATH * 2 + 256];
|
char buffer[MAXPGPATH * 3 + 256];
|
||||||
|
|
||||||
fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
|
fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -1048,7 +1056,7 @@ RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
|||||||
* Skip over first four lines (PID, pgdata, portnum, socketdir).
|
* Skip over first four lines (PID, pgdata, portnum, socketdir).
|
||||||
*/
|
*/
|
||||||
ptr = buffer;
|
ptr = buffer;
|
||||||
for (lineno = 1; lineno <= 4; lineno++)
|
for (lineno = 1; lineno < target_line; lineno++)
|
||||||
{
|
{
|
||||||
if ((ptr = strchr(ptr, '\n')) == NULL)
|
if ((ptr = strchr(ptr, '\n')) == NULL)
|
||||||
{
|
{
|
||||||
@ -1059,11 +1067,7 @@ RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
|
|||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
strlcat(buffer, str, sizeof(buffer));
|
||||||
* 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);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And rewrite the data. Since we write in a single kernel call, this
|
* And rewrite the data. Since we write in a single kernel call, this
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -138,6 +139,7 @@ static void read_post_opts(void);
|
|||||||
|
|
||||||
static PGPing test_postmaster_connection(bool);
|
static PGPing test_postmaster_connection(bool);
|
||||||
static bool postmaster_is_alive(pid_t pid);
|
static bool postmaster_is_alive(pid_t pid);
|
||||||
|
static time_t start_time;
|
||||||
|
|
||||||
static char postopts_file[MAXPGPATH];
|
static char postopts_file[MAXPGPATH];
|
||||||
static char pid_file[MAXPGPATH];
|
static char pid_file[MAXPGPATH];
|
||||||
@ -404,13 +406,13 @@ static PGPing
|
|||||||
test_postmaster_connection(bool do_checkpoint)
|
test_postmaster_connection(bool do_checkpoint)
|
||||||
{
|
{
|
||||||
int portnum = 0;
|
int portnum = 0;
|
||||||
char socket_dir[MAXPGPATH];
|
char host_str[MAXPGPATH];
|
||||||
char connstr[MAXPGPATH + 256];
|
char connstr[MAXPGPATH + 256];
|
||||||
PGPing ret = PQPING_OK; /* assume success for wait == zero */
|
PGPing ret = PQPING_OK; /* assume success for wait == zero */
|
||||||
char **optlines;
|
char **optlines;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
socket_dir[0] = '\0';
|
host_str[0] = '\0';
|
||||||
connstr[0] = '\0';
|
connstr[0] = '\0';
|
||||||
|
|
||||||
for (i = 0; i < wait_seconds; i++)
|
for (i = 0; i < wait_seconds; i++)
|
||||||
@ -425,13 +427,14 @@ test_postmaster_connection(bool do_checkpoint)
|
|||||||
* 0 lock file created but status not written
|
* 0 lock file created but status not written
|
||||||
* 2 pre-9.1 server, shared memory not created
|
* 2 pre-9.1 server, shared memory not created
|
||||||
* 3 pre-9.1 server, shared memory created
|
* 3 pre-9.1 server, shared memory created
|
||||||
* 4 9.1+ server, shared memory not created
|
* 5 9.1+ server, listen host not created
|
||||||
* 5 9.1+ server, shared memory 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
|
* 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
|
* 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
|
* written shmem key, so we fail. 9.1+ writes connection
|
||||||
* number and socket address in the file for us to use.
|
* information in the file for us to use.
|
||||||
* (PG_VERSION could also have told us the major version.)
|
* (PG_VERSION could also have told us the major version.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -439,7 +442,10 @@ test_postmaster_connection(bool do_checkpoint)
|
|||||||
if ((optlines = readfile(pid_file)) != NULL &&
|
if ((optlines = readfile(pid_file)) != NULL &&
|
||||||
optlines[0] != NULL &&
|
optlines[0] != NULL &&
|
||||||
optlines[1] != 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? */
|
/* A 3-line file? */
|
||||||
if (optlines[3] == NULL)
|
if (optlines[3] == NULL)
|
||||||
@ -459,29 +465,51 @@ test_postmaster_connection(bool do_checkpoint)
|
|||||||
return PQPING_NO_ATTEMPT;
|
return PQPING_NO_ATTEMPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* 9.1+ server */
|
else
|
||||||
{
|
{
|
||||||
portnum = atoi(optlines[2]);
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
write_stderr(_("%s: this data directory is running an older postmaster\n"),
|
||||||
|
progname);
|
||||||
|
return PQPING_NO_ATTEMPT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get socket directory, if specified. */
|
portnum = atoi(optlines[3]);
|
||||||
if (optlines[3][0] != '\n')
|
|
||||||
{
|
/*
|
||||||
|
* 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
|
* While unix_socket_directory can accept relative
|
||||||
* directories, libpq's host must have a leading slash
|
* directories, libpq's host must have a leading slash
|
||||||
* to indicate a socket directory.
|
* to indicate a socket directory.
|
||||||
*/
|
*/
|
||||||
if (optlines[3][0] != '/')
|
if (optlines[4][0] != '\n' && optlines[4][0] != '/')
|
||||||
{
|
{
|
||||||
write_stderr(_("%s: -w option cannot use a relative socket directory specification\n"),
|
write_stderr(_("%s: -w option cannot use a relative socket directory specification\n"),
|
||||||
progname);
|
progname);
|
||||||
return PQPING_NO_ATTEMPT;
|
return PQPING_NO_ATTEMPT;
|
||||||
}
|
}
|
||||||
strlcpy(socket_dir, optlines[3], MAXPGPATH);
|
strlcpy(host_str, optlines[4], sizeof(host_str));
|
||||||
|
#else
|
||||||
|
strlcpy(host_str, optlines[5], sizeof(host_str));
|
||||||
|
#endif
|
||||||
/* remove newline */
|
/* remove newline */
|
||||||
if (strchr(socket_dir, '\n') != NULL)
|
if (strchr(host_str, '\n') != NULL)
|
||||||
*strchr(socket_dir, '\n') = '\0';
|
*strchr(host_str, '\n') = '\0';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -491,9 +519,9 @@ test_postmaster_connection(bool do_checkpoint)
|
|||||||
snprintf(connstr, sizeof(connstr),
|
snprintf(connstr, sizeof(connstr),
|
||||||
"dbname=postgres port=%d connect_timeout=5", portnum);
|
"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),
|
snprintf(connstr + strlen(connstr), sizeof(connstr) - strlen(connstr),
|
||||||
" host='%s'", socket_dir);
|
" host='%s'", host_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,6 +1784,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
progname = get_progname(argv[0]);
|
progname = get_progname(argv[0]);
|
||||||
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));
|
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
|
* save argv[0] so do_start() can look for the postmaster if necessary. we
|
||||||
|
@ -348,11 +348,11 @@ extern PGDLLIMPORT bool process_shared_preload_libraries_in_progress;
|
|||||||
extern char *shared_preload_libraries_string;
|
extern char *shared_preload_libraries_string;
|
||||||
extern char *local_preload_libraries_string;
|
extern char *local_preload_libraries_string;
|
||||||
|
|
||||||
|
#define LOCK_FILE_LINES 7
|
||||||
extern void CreateDataDirLockFile(bool amPostmaster);
|
extern void CreateDataDirLockFile(bool amPostmaster);
|
||||||
extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster);
|
extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster);
|
||||||
extern void TouchSocketLockFile(void);
|
extern void TouchSocketLockFile(void);
|
||||||
extern void RecordSharedMemoryInLockFile(unsigned long id1,
|
extern void AddToLockFile(int target_line, const char *str);
|
||||||
unsigned long id2);
|
|
||||||
extern void ValidatePgVersion(const char *path);
|
extern void ValidatePgVersion(const char *path);
|
||||||
extern void process_shared_preload_libraries(void);
|
extern void process_shared_preload_libraries(void);
|
||||||
extern void process_local_preload_libraries(void);
|
extern void process_local_preload_libraries(void);
|
||||||
|
Reference in New Issue
Block a user