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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy