aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/test/regress/pg_regress.c111
1 files changed, 103 insertions, 8 deletions
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 803cf903db4..27c46abc96a 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -30,6 +30,7 @@
#endif
#include "getopt_long.h"
+#include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
#include "pg_config_paths.h"
/* for resultmap we need a list of pairs of strings */
@@ -109,6 +110,12 @@ static const char *progname;
static char *logfilename;
static FILE *logfile;
static char *difffilename;
+static const char *sockdir;
+#ifdef HAVE_UNIX_SOCKETS
+static const char *temp_sockdir;
+static char sockself[MAXPGPATH];
+static char socklock[MAXPGPATH];
+#endif
static _resultmap *resultmap = NULL;
@@ -307,6 +314,82 @@ stop_postmaster(void)
}
}
+#ifdef HAVE_UNIX_SOCKETS
+/*
+ * Remove the socket temporary directory. pg_regress never waits for a
+ * postmaster exit, so it is indeterminate whether the postmaster has yet to
+ * unlink the socket and lock file. Unlink them here so we can proceed to
+ * remove the directory. Ignore errors; leaking a temporary directory is
+ * unimportant. This can run from a signal handler. The code is not
+ * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
+ * Windows is not a HAVE_UNIX_SOCKETS platform.
+ */
+static void
+remove_temp(void)
+{
+ Assert(temp_sockdir);
+ unlink(sockself);
+ unlink(socklock);
+ rmdir(temp_sockdir);
+}
+
+/*
+ * Signal handler that calls remove_temp() and reraises the signal.
+ */
+static void
+signal_remove_temp(int signum)
+{
+ remove_temp();
+
+ pqsignal(signum, SIG_DFL);
+ raise(signum);
+}
+
+/*
+ * Create a temporary directory suitable for the server's Unix-domain socket.
+ * The directory will have mode 0700 or stricter, so no other OS user can open
+ * our socket to exploit our use of trust authentication. Most systems
+ * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
+ * place the directory under /tmp rather than relative to the possibly-deep
+ * current working directory.
+ *
+ * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
+ * testing to work in builds that relocate it to a directory not writable to
+ * the build/test user.
+ */
+static const char *
+make_temp_sockdir(void)
+{
+ char *template = strdup("/tmp/pg_regress-XXXXXX");
+
+ temp_sockdir = mkdtemp(template);
+ if (temp_sockdir == NULL)
+ {
+ fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
+ progname, template, strerror(errno));
+ exit(2);
+ }
+
+ /* Stage file names for remove_temp(). Unsafe in a signal handler. */
+ UNIXSOCK_PATH(sockself, port, temp_sockdir);
+ snprintf(socklock, sizeof(socklock), "%s.lock", sockself);
+
+ /* Remove the directory during clean exit. */
+ atexit(remove_temp);
+
+ /*
+ * Remove the directory before dying to the usual signals. Omit SIGQUIT,
+ * preserving it as a quick, untidy exit.
+ */
+ pqsignal(SIGHUP, signal_remove_temp);
+ pqsignal(SIGINT, signal_remove_temp);
+ pqsignal(SIGPIPE, signal_remove_temp);
+ pqsignal(SIGTERM, signal_remove_temp);
+
+ return temp_sockdir;
+}
+#endif /* HAVE_UNIX_SOCKETS */
+
/*
* Check whether string matches pattern
*
@@ -759,8 +842,7 @@ initialize_environment(void)
* the wrong postmaster, or otherwise behave in nondefault ways. (Note
* we also use psql's -X switch consistently, so that ~/.psqlrc files
* won't mess things up.) Also, set PGPORT to the temp port, and set
- * or unset PGHOST depending on whether we are using TCP or Unix
- * sockets.
+ * PGHOST depending on whether we are using TCP or Unix sockets.
*/
unsetenv("PGDATABASE");
unsetenv("PGUSER");
@@ -769,10 +851,20 @@ initialize_environment(void)
unsetenv("PGREQUIRESSL");
unsetenv("PGCONNECT_TIMEOUT");
unsetenv("PGDATA");
+#ifdef HAVE_UNIX_SOCKETS
if (hostname != NULL)
doputenv("PGHOST", hostname);
else
- unsetenv("PGHOST");
+ {
+ sockdir = getenv("PG_REGRESS_SOCK_DIR");
+ if (!sockdir)
+ sockdir = make_temp_sockdir();
+ doputenv("PGHOST", sockdir);
+ }
+#else
+ Assert(hostname != NULL);
+ doputenv("PGHOST", hostname);
+#endif
unsetenv("PGHOSTADDR");
if (port != -1)
{
@@ -2067,7 +2159,9 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
/*
* To reduce chances of interference with parallel installations, use
* a port number starting in the private range (49152-65535)
- * calculated from the version number.
+ * calculated from the version number. This aids !HAVE_UNIX_SOCKETS
+ * systems; elsewhere, the use of a private socket directory already
+ * prevents interference.
*/
port = 0xC000 | (PG_VERSION_NUM & 0x3FFF);
@@ -2240,10 +2334,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
*/
header(_("starting postmaster"));
snprintf(buf, sizeof(buf),
- "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1",
- bindir, temp_install,
- debug ? " -d 5" : "",
- hostname ? hostname : "",
+ "\"%s/postgres\" -D \"%s/data\" -F%s "
+ "-c \"listen_addresses=%s\" -k \"%s\" "
+ "> \"%s/log/postmaster.log\" 2>&1",
+ bindir, temp_install, debug ? " -d 5" : "",
+ hostname ? hostname : "", sockdir ? sockdir : "",
outputdir);
postmaster_pid = spawn_process(buf);
if (postmaster_pid == INVALID_PID)