30
30
#endif
31
31
32
32
#include "getopt_long.h"
33
+ #include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
34
+ #include "libpq/pqsignal.h"
33
35
#include "pg_config_paths.h"
34
36
35
37
/* for resultmap we need a list of pairs of strings */
@@ -109,6 +111,12 @@ static const char *progname;
109
111
static char * logfilename ;
110
112
static FILE * logfile ;
111
113
static char * difffilename ;
114
+ static const char * sockdir ;
115
+ #ifdef HAVE_UNIX_SOCKETS
116
+ static const char * temp_sockdir ;
117
+ static char sockself [MAXPGPATH ];
118
+ static char socklock [MAXPGPATH ];
119
+ #endif
112
120
113
121
static _resultmap * resultmap = NULL ;
114
122
@@ -307,6 +315,81 @@ stop_postmaster(void)
307
315
}
308
316
}
309
317
318
+ #ifdef HAVE_UNIX_SOCKETS
319
+ /*
320
+ * Remove the socket temporary directory. pg_regress never waits for a
321
+ * postmaster exit, so it is indeterminate whether the postmaster has yet to
322
+ * unlink the socket and lock file. Unlink them here so we can proceed to
323
+ * remove the directory. Ignore errors; leaking a temporary directory is
324
+ * unimportant. This can run from a signal handler. The code is not
325
+ * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
326
+ * Windows is not a HAVE_UNIX_SOCKETS platform.
327
+ */
328
+ static void
329
+ remove_temp (void )
330
+ {
331
+ unlink (sockself );
332
+ unlink (socklock );
333
+ rmdir (temp_sockdir );
334
+ }
335
+
336
+ /*
337
+ * Signal handler that calls remove_temp() and reraises the signal.
338
+ */
339
+ static void
340
+ signal_remove_temp (int signum )
341
+ {
342
+ remove_temp ();
343
+
344
+ pqsignal (signum , SIG_DFL );
345
+ raise (signum );
346
+ }
347
+
348
+ /*
349
+ * Create a temporary directory suitable for the server's Unix-domain socket.
350
+ * The directory will have mode 0700 or stricter, so no other OS user can open
351
+ * our socket to exploit our use of trust authentication. Most systems
352
+ * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
353
+ * place the directory under /tmp rather than relative to the possibly-deep
354
+ * current working directory.
355
+ *
356
+ * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
357
+ * testing to work in builds that relocate it to a directory not writable to
358
+ * the build/test user.
359
+ */
360
+ static const char *
361
+ make_temp_sockdir (void )
362
+ {
363
+ char * template = strdup ("/tmp/pg_regress-XXXXXX" );
364
+
365
+ temp_sockdir = mkdtemp (template );
366
+ if (temp_sockdir == NULL )
367
+ {
368
+ fprintf (stderr , _ ("%s: could not create directory \"%s\": %s\n" ),
369
+ progname , template , strerror (errno ));
370
+ exit (2 );
371
+ }
372
+
373
+ /* Stage file names for remove_temp(). Unsafe in a signal handler. */
374
+ UNIXSOCK_PATH (sockself , port , temp_sockdir );
375
+ snprintf (socklock , sizeof (socklock ), "%s.lock" , sockself );
376
+
377
+ /* Remove the directory during clean exit. */
378
+ atexit (remove_temp );
379
+
380
+ /*
381
+ * Remove the directory before dying to the usual signals. Omit SIGQUIT,
382
+ * preserving it as a quick, untidy exit.
383
+ */
384
+ pqsignal (SIGHUP , signal_remove_temp );
385
+ pqsignal (SIGINT , signal_remove_temp );
386
+ pqsignal (SIGPIPE , signal_remove_temp );
387
+ pqsignal (SIGTERM , signal_remove_temp );
388
+
389
+ return temp_sockdir ;
390
+ }
391
+ #endif /* HAVE_UNIX_SOCKETS */
392
+
310
393
/*
311
394
* Check whether string matches pattern
312
395
*
@@ -759,8 +842,7 @@ initialize_environment(void)
759
842
* the wrong postmaster, or otherwise behave in nondefault ways. (Note
760
843
* we also use psql's -X switch consistently, so that ~/.psqlrc files
761
844
* won't mess things up.) Also, set PGPORT to the temp port, and set
762
- * or unset PGHOST depending on whether we are using TCP or Unix
763
- * sockets.
845
+ * PGHOST depending on whether we are using TCP or Unix sockets.
764
846
*/
765
847
unsetenv ("PGDATABASE" );
766
848
unsetenv ("PGUSER" );
@@ -769,10 +851,19 @@ initialize_environment(void)
769
851
unsetenv ("PGREQUIRESSL" );
770
852
unsetenv ("PGCONNECT_TIMEOUT" );
771
853
unsetenv ("PGDATA" );
854
+ #ifdef HAVE_UNIX_SOCKETS
772
855
if (hostname != NULL )
773
856
doputenv ("PGHOST" , hostname );
774
857
else
775
- unsetenv ("PGHOST" );
858
+ {
859
+ sockdir = getenv ("PG_REGRESS_SOCK_DIR" );
860
+ if (!sockdir )
861
+ sockdir = make_temp_sockdir ();
862
+ doputenv ("PGHOST" , sockdir );
863
+ }
864
+ #else
865
+ doputenv ("PGHOST" , hostname );
866
+ #endif
776
867
unsetenv ("PGHOSTADDR" );
777
868
if (port != -1 )
778
869
{
@@ -2077,7 +2168,9 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2077
2168
/*
2078
2169
* To reduce chances of interference with parallel installations, use
2079
2170
* a port number starting in the private range (49152-65535)
2080
- * calculated from the version number.
2171
+ * calculated from the version number. This aids !HAVE_UNIX_SOCKETS
2172
+ * systems; elsewhere, the use of a private socket directory already
2173
+ * prevents interference.
2081
2174
*/
2082
2175
port = 0xC000 | (PG_VERSION_NUM & 0x3FFF );
2083
2176
@@ -2246,10 +2339,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2246
2339
*/
2247
2340
header (_ ("starting postmaster" ));
2248
2341
snprintf (buf , sizeof (buf ),
2249
- SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE ,
2250
- bindir , temp_install ,
2251
- debug ? " -d 5" : "" ,
2252
- hostname ? hostname : "" ,
2342
+ SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s "
2343
+ "-c \"listen_addresses=%s\" -k \"%s\" "
2344
+ "> \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE ,
2345
+ bindir , temp_install , debug ? " -d 5" : "" ,
2346
+ hostname ? hostname : "" , sockdir ? sockdir : "" ,
2253
2347
outputdir );
2254
2348
postmaster_pid = spawn_process (buf );
2255
2349
if (postmaster_pid == INVALID_PID )
0 commit comments