pg_ctl: improve handling of invalid data directory

Return '4' and report a meaningful error message when a non-existent or
invalid data directory is passed.  Previously, pg_ctl would just report
the server was not running.

Patch by me and Amit Kapila
Report from Peter Eisentraut
This commit is contained in:
Bruce Momjian 2014-03-08 12:15:25 -05:00
parent 3624acd342
commit 11d205e2bd
2 changed files with 39 additions and 12 deletions

View File

@ -208,7 +208,8 @@ PostgreSQL documentation
the specified data directory. If it is, the <acronym>PID</acronym>
and the command line options that were used to invoke it are
displayed. If the server is not running, the process returns an
exit status of 3.
exit status of 3. If an accessible data directory is not specified,
the process returns an exit status of 4.
</para>
<para>

View File

@ -97,6 +97,7 @@ static bool allow_core_files = false;
static time_t start_time;
static char postopts_file[MAXPGPATH];
static char version_file[MAXPGPATH];
static char pid_file[MAXPGPATH];
static char backup_file[MAXPGPATH];
static char recovery_file[MAXPGPATH];
@ -152,7 +153,7 @@ static void pgwin32_doRunAsService(void);
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service);
#endif
static pgpid_t get_pgpid(void);
static pgpid_t get_pgpid(bool is_status_request);
static char **readfile(const char *path);
static void free_readfile(char **optlines);
static int start_postmaster(void);
@ -246,10 +247,34 @@ print_msg(const char *msg)
}
static pgpid_t
get_pgpid(void)
get_pgpid(bool is_status_request)
{
FILE *pidf;
long pid;
struct stat statbuf;
if (stat(pg_data, &statbuf) != 0)
{
if (errno == ENOENT)
printf(_("%s: directory \"%s\" does not exist\n"), progname,
pg_data);
else
printf(_("%s: cannot access directory \"%s\"\n"), progname,
pg_data);
/*
* The Linux Standard Base Core Specification 3.1 says this should return
* '4, program or service status is unknown'
* https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
*/
exit(is_status_request ? 4 : 1);
}
if (stat(version_file, &statbuf) != 0 && errno == ENOENT)
{
printf(_("%s: directory \"%s\" is not a database cluster directory\n"),
progname, pg_data);
exit(is_status_request ? 4 : 1);
}
pidf = fopen(pid_file, "r");
if (pidf == NULL)
@ -810,7 +835,7 @@ do_start(void)
if (ctl_command != RESTART_COMMAND)
{
old_pid = get_pgpid();
old_pid = get_pgpid(false);
if (old_pid != 0)
write_stderr(_("%s: another server might be running; "
"trying to start server anyway\n"),
@ -894,7 +919,7 @@ do_stop(void)
pgpid_t pid;
struct stat statbuf;
pid = get_pgpid();
pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
@ -943,7 +968,7 @@ do_stop(void)
for (cnt = 0; cnt < wait_seconds; cnt++)
{
if ((pid = get_pgpid()) != 0)
if ((pid = get_pgpid(false)) != 0)
{
print_msg(".");
pg_usleep(1000000); /* 1 sec */
@ -980,7 +1005,7 @@ do_restart(void)
pgpid_t pid;
struct stat statbuf;
pid = get_pgpid();
pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
@ -1033,7 +1058,7 @@ do_restart(void)
for (cnt = 0; cnt < wait_seconds; cnt++)
{
if ((pid = get_pgpid()) != 0)
if ((pid = get_pgpid(false)) != 0)
{
print_msg(".");
pg_usleep(1000000); /* 1 sec */
@ -1071,7 +1096,7 @@ do_reload(void)
{
pgpid_t pid;
pid = get_pgpid();
pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
@ -1110,7 +1135,7 @@ do_promote(void)
pgpid_t pid;
struct stat statbuf;
pid = get_pgpid();
pid = get_pgpid(false);
if (pid == 0) /* no pid file */
{
@ -1204,7 +1229,7 @@ do_status(void)
{
pgpid_t pid;
pid = get_pgpid();
pid = get_pgpid(true);
/* Is there a pid file? */
if (pid != 0)
{
@ -1247,7 +1272,7 @@ do_status(void)
/*
* The Linux Standard Base Core Specification 3.1 says this should return
* '3'
* '3, program is not running'
* https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
*/
exit(3);
@ -2285,6 +2310,7 @@ main(int argc, char **argv)
if (pg_data)
{
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
snprintf(version_file, MAXPGPATH, "%s/PG_VERSION", pg_data);
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);