Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5945283

Browse files
committed
Try to improve error handling for failures of backend subprocess.
1 parent e035a29 commit 5945283

File tree

1 file changed

+72
-23
lines changed

1 file changed

+72
-23
lines changed

src/bin/initdb/initdb.c

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
4343
* Portions Copyright (c) 1994, Regents of the University of California
4444
*
45-
* $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.9 2003/11/14 17:30:41 tgl Exp $
45+
* $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.10 2003/11/14 18:32:34 tgl Exp $
4646
*
4747
*-------------------------------------------------------------------------
4848
*/
@@ -51,6 +51,7 @@
5151

5252
#include <dirent.h>
5353
#include <sys/stat.h>
54+
#include <sys/wait.h>
5455
#include <unistd.h>
5556
#include <locale.h>
5657
#include <signal.h>
@@ -112,8 +113,10 @@ char *system_views_file;
112113
char *effective_user;
113114
bool testpath = true;
114115
bool made_new_pgdata = false;
116+
bool found_existing_pgdata = false;
115117
char infoversion[100];
116-
bool not_ok = false;
118+
bool caught_signal = false;
119+
bool output_failed = false;
117120

118121
/* defaults */
119122
int n_connections = 10;
@@ -159,6 +162,7 @@ static char *expanded_path(char *);
159162
#endif
160163
static char **readfile(char *);
161164
static void writefile(char *, char **);
165+
static void pclose_check(FILE *stream);
162166
static char *get_id(void);
163167
static char *get_encoding_id(char *);
164168
static char *get_short_version(void);
@@ -206,22 +210,20 @@ static void *xmalloc(size_t);
206210
do { \
207211
fflush(stdout); \
208212
fflush(stderr); \
209-
pg = popen(cmd, PG_BINARY_W); \
213+
pg = popen(cmd, "w"); \
210214
if (pg == NULL) \
211215
exit_nicely(); \
212216
} while (0)
213217

214218
#define PG_CMD_CLOSE \
215219
do { \
216-
if ((pclose(pg) >> 8) & 0xff) \
217-
exit_nicely(); \
220+
pclose_check(pg); \
218221
} while (0)
219222

220223
#define PG_CMD_PUTLINE \
221224
do { \
222-
if (fputs(*line, pg) < 0) \
223-
exit_nicely(); \
224-
fflush(pg); \
225+
if (fputs(*line, pg) < 0 || fflush(pg) < 0) \
226+
output_failed = true; \
225227
} while (0)
226228

227229
#ifndef WIN32
@@ -460,6 +462,41 @@ writefile(char *path, char **lines)
460462
exit_nicely();
461463
}
462464

465+
/* pclose() plus useful error reporting */
466+
static void
467+
pclose_check(FILE *stream)
468+
{
469+
int exitstatus;
470+
471+
exitstatus = pclose(stream);
472+
473+
if (exitstatus == 0)
474+
return; /* all is well */
475+
476+
if (exitstatus == -1)
477+
{
478+
/* pclose() itself failed, and hopefully set errno */
479+
perror("pclose failed");
480+
}
481+
else if (WIFEXITED(exitstatus))
482+
{
483+
fprintf(stderr, "child process exited with exit code %d\n",
484+
WEXITSTATUS(exitstatus));
485+
}
486+
else if (WIFSIGNALED(exitstatus))
487+
{
488+
fprintf(stderr, "child process was terminated by signal %d\n",
489+
WTERMSIG(exitstatus));
490+
}
491+
else
492+
{
493+
fprintf(stderr, "child process exited with unexpected status %d\n",
494+
exitstatus);
495+
}
496+
497+
exit_nicely();
498+
}
499+
463500
/* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
464501

465502
/*
@@ -585,21 +622,24 @@ exit_nicely(void)
585622
if (!rmtree(pg_data, true))
586623
fprintf(stderr, "%s: failed\n", progname);
587624
}
588-
else
625+
else if (found_existing_pgdata)
589626
{
590627
fprintf(stderr,
591628
"%s: removing contents of data directory \"%s\"\n",
592629
progname, pg_data);
593630
if (!rmtree(pg_data, false))
594631
fprintf(stderr, "%s: failed\n", progname);
595632
}
633+
/* otherwise died during startup, do nothing! */
596634
}
597635
else
598636
{
599-
fprintf(stderr,
600-
"%s: data directory \"%s\" not removed at user's request\n",
601-
progname, pg_data);
637+
if (made_new_pgdata || found_existing_pgdata)
638+
fprintf(stderr,
639+
"%s: data directory \"%s\" not removed at user's request\n",
640+
progname, pg_data);
602641
}
642+
603643
exit(1);
604644
}
605645

@@ -874,7 +914,7 @@ find_postgres(char *path)
874914
if (fgets(line, sizeof(line), pgver) == NULL)
875915
perror("fgets failure");
876916

877-
pclose(pgver);
917+
pclose_check(pgver);
878918

879919
if (strcmp(line, PG_VERSIONSTR) != 0)
880920
return FIND_WRONG_VERSION;
@@ -1839,7 +1879,7 @@ trapsig(int signum)
18391879
{
18401880
/* handle systems that reset the handler, like Windows (grr) */
18411881
pqsignal(signum, trapsig);
1842-
not_ok = true;
1882+
caught_signal = true;
18431883
}
18441884

18451885
/*
@@ -1848,14 +1888,19 @@ trapsig(int signum)
18481888
static void
18491889
check_ok()
18501890
{
1851-
if (not_ok)
1891+
if (caught_signal)
1892+
{
1893+
printf("caught signal\n");
1894+
exit_nicely();
1895+
}
1896+
else if (output_failed)
18521897
{
1853-
printf("Caught Signal.\n");
1898+
printf("failed to write to child process\n");
18541899
exit_nicely();
18551900
}
18561901
else
18571902
{
1858-
/* no signal caught */
1903+
/* all seems well */
18591904
printf("ok\n");
18601905
}
18611906
}
@@ -2329,6 +2374,11 @@ main(int argc, char *argv[])
23292374
pqsignal(SIGTERM, trapsig);
23302375
#endif
23312376

2377+
/* Ignore SIGPIPE when writing to backend, so we can clean up */
2378+
#ifdef SIGPIPE
2379+
pqsignal(SIGPIPE, SIG_IGN);
2380+
#endif
2381+
23322382
switch (check_data_dir())
23332383
{
23342384
case 0:
@@ -2354,11 +2404,12 @@ main(int argc, char *argv[])
23542404
if (chmod(pg_data, 0700) != 0)
23552405
{
23562406
perror(pg_data);
2357-
/* don't exit_nicely(), it'll try to remove pg_data contents */
2358-
exit(1);
2407+
exit_nicely();
23592408
}
23602409
else
23612410
check_ok();
2411+
2412+
found_existing_pgdata = true;
23622413
break;
23632414

23642415
case 2:
@@ -2369,14 +2420,12 @@ main(int argc, char *argv[])
23692420
"the directory \"%s\" or run %s\n"
23702421
"with an argument other than \"%s\".\n",
23712422
progname, pg_data, pg_data, progname, pg_data);
2372-
/* don't exit_nicely(), it'll try to remove pg_data contents */
2373-
exit(1);
2423+
exit(1); /* no further message needed */
23742424

23752425
default:
23762426
/* Trouble accessing directory */
23772427
perror(pg_data);
2378-
/* don't exit_nicely(), it'll try to remove pg_data contents */
2379-
exit(1);
2428+
exit_nicely();
23802429
}
23812430

23822431
/* Create required subdirectories */

0 commit comments

Comments
 (0)