Skip to content

Commit 11d205e

Browse files
committed
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
1 parent 3624acd commit 11d205e

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

doc/src/sgml/ref/pg_ctl-ref.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ PostgreSQL documentation
208208
the specified data directory. If it is, the <acronym>PID</acronym>
209209
and the command line options that were used to invoke it are
210210
displayed. If the server is not running, the process returns an
211-
exit status of 3.
211+
exit status of 3. If an accessible data directory is not specified,
212+
the process returns an exit status of 4.
212213
</para>
213214

214215
<para>

src/bin/pg_ctl/pg_ctl.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ static bool allow_core_files = false;
9797
static time_t start_time;
9898

9999
static char postopts_file[MAXPGPATH];
100+
static char version_file[MAXPGPATH];
100101
static char pid_file[MAXPGPATH];
101102
static char backup_file[MAXPGPATH];
102103
static char recovery_file[MAXPGPATH];
@@ -152,7 +153,7 @@ static void pgwin32_doRunAsService(void);
152153
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, bool as_service);
153154
#endif
154155

155-
static pgpid_t get_pgpid(void);
156+
static pgpid_t get_pgpid(bool is_status_request);
156157
static char **readfile(const char *path);
157158
static void free_readfile(char **optlines);
158159
static int start_postmaster(void);
@@ -246,10 +247,34 @@ print_msg(const char *msg)
246247
}
247248

248249
static pgpid_t
249-
get_pgpid(void)
250+
get_pgpid(bool is_status_request)
250251
{
251252
FILE *pidf;
252253
long pid;
254+
struct stat statbuf;
255+
256+
if (stat(pg_data, &statbuf) != 0)
257+
{
258+
if (errno == ENOENT)
259+
printf(_("%s: directory \"%s\" does not exist\n"), progname,
260+
pg_data);
261+
else
262+
printf(_("%s: cannot access directory \"%s\"\n"), progname,
263+
pg_data);
264+
/*
265+
* The Linux Standard Base Core Specification 3.1 says this should return
266+
* '4, program or service status is unknown'
267+
* https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
268+
*/
269+
exit(is_status_request ? 4 : 1);
270+
}
271+
272+
if (stat(version_file, &statbuf) != 0 && errno == ENOENT)
273+
{
274+
printf(_("%s: directory \"%s\" is not a database cluster directory\n"),
275+
progname, pg_data);
276+
exit(is_status_request ? 4 : 1);
277+
}
253278

254279
pidf = fopen(pid_file, "r");
255280
if (pidf == NULL)
@@ -810,7 +835,7 @@ do_start(void)
810835

811836
if (ctl_command != RESTART_COMMAND)
812837
{
813-
old_pid = get_pgpid();
838+
old_pid = get_pgpid(false);
814839
if (old_pid != 0)
815840
write_stderr(_("%s: another server might be running; "
816841
"trying to start server anyway\n"),
@@ -894,7 +919,7 @@ do_stop(void)
894919
pgpid_t pid;
895920
struct stat statbuf;
896921

897-
pid = get_pgpid();
922+
pid = get_pgpid(false);
898923

899924
if (pid == 0) /* no pid file */
900925
{
@@ -943,7 +968,7 @@ do_stop(void)
943968

944969
for (cnt = 0; cnt < wait_seconds; cnt++)
945970
{
946-
if ((pid = get_pgpid()) != 0)
971+
if ((pid = get_pgpid(false)) != 0)
947972
{
948973
print_msg(".");
949974
pg_usleep(1000000); /* 1 sec */
@@ -980,7 +1005,7 @@ do_restart(void)
9801005
pgpid_t pid;
9811006
struct stat statbuf;
9821007

983-
pid = get_pgpid();
1008+
pid = get_pgpid(false);
9841009

9851010
if (pid == 0) /* no pid file */
9861011
{
@@ -1033,7 +1058,7 @@ do_restart(void)
10331058

10341059
for (cnt = 0; cnt < wait_seconds; cnt++)
10351060
{
1036-
if ((pid = get_pgpid()) != 0)
1061+
if ((pid = get_pgpid(false)) != 0)
10371062
{
10381063
print_msg(".");
10391064
pg_usleep(1000000); /* 1 sec */
@@ -1071,7 +1096,7 @@ do_reload(void)
10711096
{
10721097
pgpid_t pid;
10731098

1074-
pid = get_pgpid();
1099+
pid = get_pgpid(false);
10751100
if (pid == 0) /* no pid file */
10761101
{
10771102
write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
@@ -1110,7 +1135,7 @@ do_promote(void)
11101135
pgpid_t pid;
11111136
struct stat statbuf;
11121137

1113-
pid = get_pgpid();
1138+
pid = get_pgpid(false);
11141139

11151140
if (pid == 0) /* no pid file */
11161141
{
@@ -1204,7 +1229,7 @@ do_status(void)
12041229
{
12051230
pgpid_t pid;
12061231

1207-
pid = get_pgpid();
1232+
pid = get_pgpid(true);
12081233
/* Is there a pid file? */
12091234
if (pid != 0)
12101235
{
@@ -1247,7 +1272,7 @@ do_status(void)
12471272

12481273
/*
12491274
* The Linux Standard Base Core Specification 3.1 says this should return
1250-
* '3'
1275+
* '3, program is not running'
12511276
* https://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
12521277
*/
12531278
exit(3);
@@ -2285,6 +2310,7 @@ main(int argc, char **argv)
22852310
if (pg_data)
22862311
{
22872312
snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
2313+
snprintf(version_file, MAXPGPATH, "%s/PG_VERSION", pg_data);
22882314
snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
22892315
snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
22902316
snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);

0 commit comments

Comments
 (0)