Skip to content
Snippets Groups Projects
Commit 59452835 authored by Tom Lane's avatar Tom Lane
Browse files

Try to improve error handling for failures of backend subprocess.

parent e035a297
No related branches found
No related tags found
No related merge requests found
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.9 2003/11/14 17:30:41 tgl Exp $ * $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.10 2003/11/14 18:32:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include <locale.h> #include <locale.h>
#include <signal.h> #include <signal.h>
...@@ -112,8 +113,10 @@ char *system_views_file; ...@@ -112,8 +113,10 @@ char *system_views_file;
char *effective_user; char *effective_user;
bool testpath = true; bool testpath = true;
bool made_new_pgdata = false; bool made_new_pgdata = false;
bool found_existing_pgdata = false;
char infoversion[100]; char infoversion[100];
bool not_ok = false; bool caught_signal = false;
bool output_failed = false;
/* defaults */ /* defaults */
int n_connections = 10; int n_connections = 10;
...@@ -159,6 +162,7 @@ static char *expanded_path(char *); ...@@ -159,6 +162,7 @@ static char *expanded_path(char *);
#endif #endif
static char **readfile(char *); static char **readfile(char *);
static void writefile(char *, char **); static void writefile(char *, char **);
static void pclose_check(FILE *stream);
static char *get_id(void); static char *get_id(void);
static char *get_encoding_id(char *); static char *get_encoding_id(char *);
static char *get_short_version(void); static char *get_short_version(void);
...@@ -206,22 +210,20 @@ static void *xmalloc(size_t); ...@@ -206,22 +210,20 @@ static void *xmalloc(size_t);
do { \ do { \
fflush(stdout); \ fflush(stdout); \
fflush(stderr); \ fflush(stderr); \
pg = popen(cmd, PG_BINARY_W); \ pg = popen(cmd, "w"); \
if (pg == NULL) \ if (pg == NULL) \
exit_nicely(); \ exit_nicely(); \
} while (0) } while (0)
#define PG_CMD_CLOSE \ #define PG_CMD_CLOSE \
do { \ do { \
if ((pclose(pg) >> 8) & 0xff) \ pclose_check(pg); \
exit_nicely(); \
} while (0) } while (0)
#define PG_CMD_PUTLINE \ #define PG_CMD_PUTLINE \
do { \ do { \
if (fputs(*line, pg) < 0) \ if (fputs(*line, pg) < 0 || fflush(pg) < 0) \
exit_nicely(); \ output_failed = true; \
fflush(pg); \
} while (0) } while (0)
#ifndef WIN32 #ifndef WIN32
...@@ -460,6 +462,41 @@ writefile(char *path, char **lines) ...@@ -460,6 +462,41 @@ writefile(char *path, char **lines)
exit_nicely(); exit_nicely();
} }
/* pclose() plus useful error reporting */
static void
pclose_check(FILE *stream)
{
int exitstatus;
exitstatus = pclose(stream);
if (exitstatus == 0)
return; /* all is well */
if (exitstatus == -1)
{
/* pclose() itself failed, and hopefully set errno */
perror("pclose failed");
}
else if (WIFEXITED(exitstatus))
{
fprintf(stderr, "child process exited with exit code %d\n",
WEXITSTATUS(exitstatus));
}
else if (WIFSIGNALED(exitstatus))
{
fprintf(stderr, "child process was terminated by signal %d\n",
WTERMSIG(exitstatus));
}
else
{
fprintf(stderr, "child process exited with unexpected status %d\n",
exitstatus);
}
exit_nicely();
}
/* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */ /* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
/* /*
...@@ -585,7 +622,7 @@ exit_nicely(void) ...@@ -585,7 +622,7 @@ exit_nicely(void)
if (!rmtree(pg_data, true)) if (!rmtree(pg_data, true))
fprintf(stderr, "%s: failed\n", progname); fprintf(stderr, "%s: failed\n", progname);
} }
else else if (found_existing_pgdata)
{ {
fprintf(stderr, fprintf(stderr,
"%s: removing contents of data directory \"%s\"\n", "%s: removing contents of data directory \"%s\"\n",
...@@ -593,13 +630,16 @@ exit_nicely(void) ...@@ -593,13 +630,16 @@ exit_nicely(void)
if (!rmtree(pg_data, false)) if (!rmtree(pg_data, false))
fprintf(stderr, "%s: failed\n", progname); fprintf(stderr, "%s: failed\n", progname);
} }
/* otherwise died during startup, do nothing! */
} }
else else
{ {
fprintf(stderr, if (made_new_pgdata || found_existing_pgdata)
"%s: data directory \"%s\" not removed at user's request\n", fprintf(stderr,
progname, pg_data); "%s: data directory \"%s\" not removed at user's request\n",
progname, pg_data);
} }
exit(1); exit(1);
} }
...@@ -874,7 +914,7 @@ find_postgres(char *path) ...@@ -874,7 +914,7 @@ find_postgres(char *path)
if (fgets(line, sizeof(line), pgver) == NULL) if (fgets(line, sizeof(line), pgver) == NULL)
perror("fgets failure"); perror("fgets failure");
pclose(pgver); pclose_check(pgver);
if (strcmp(line, PG_VERSIONSTR) != 0) if (strcmp(line, PG_VERSIONSTR) != 0)
return FIND_WRONG_VERSION; return FIND_WRONG_VERSION;
...@@ -1839,7 +1879,7 @@ trapsig(int signum) ...@@ -1839,7 +1879,7 @@ trapsig(int signum)
{ {
/* handle systems that reset the handler, like Windows (grr) */ /* handle systems that reset the handler, like Windows (grr) */
pqsignal(signum, trapsig); pqsignal(signum, trapsig);
not_ok = true; caught_signal = true;
} }
/* /*
...@@ -1848,14 +1888,19 @@ trapsig(int signum) ...@@ -1848,14 +1888,19 @@ trapsig(int signum)
static void static void
check_ok() check_ok()
{ {
if (not_ok) if (caught_signal)
{
printf("caught signal\n");
exit_nicely();
}
else if (output_failed)
{ {
printf("Caught Signal.\n"); printf("failed to write to child process\n");
exit_nicely(); exit_nicely();
} }
else else
{ {
/* no signal caught */ /* all seems well */
printf("ok\n"); printf("ok\n");
} }
} }
...@@ -2329,6 +2374,11 @@ main(int argc, char *argv[]) ...@@ -2329,6 +2374,11 @@ main(int argc, char *argv[])
pqsignal(SIGTERM, trapsig); pqsignal(SIGTERM, trapsig);
#endif #endif
/* Ignore SIGPIPE when writing to backend, so we can clean up */
#ifdef SIGPIPE
pqsignal(SIGPIPE, SIG_IGN);
#endif
switch (check_data_dir()) switch (check_data_dir())
{ {
case 0: case 0:
...@@ -2354,11 +2404,12 @@ main(int argc, char *argv[]) ...@@ -2354,11 +2404,12 @@ main(int argc, char *argv[])
if (chmod(pg_data, 0700) != 0) if (chmod(pg_data, 0700) != 0)
{ {
perror(pg_data); perror(pg_data);
/* don't exit_nicely(), it'll try to remove pg_data contents */ exit_nicely();
exit(1);
} }
else else
check_ok(); check_ok();
found_existing_pgdata = true;
break; break;
case 2: case 2:
...@@ -2369,14 +2420,12 @@ main(int argc, char *argv[]) ...@@ -2369,14 +2420,12 @@ main(int argc, char *argv[])
"the directory \"%s\" or run %s\n" "the directory \"%s\" or run %s\n"
"with an argument other than \"%s\".\n", "with an argument other than \"%s\".\n",
progname, pg_data, pg_data, progname, pg_data); progname, pg_data, pg_data, progname, pg_data);
/* don't exit_nicely(), it'll try to remove pg_data contents */ exit(1); /* no further message needed */
exit(1);
default: default:
/* Trouble accessing directory */ /* Trouble accessing directory */
perror(pg_data); perror(pg_data);
/* don't exit_nicely(), it'll try to remove pg_data contents */ exit_nicely();
exit(1);
} }
/* Create required subdirectories */ /* Create required subdirectories */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment