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 */
@@ -96,6 +98,12 @@ static const char *progname;
96
98
static char * logfilename ;
97
99
static FILE * logfile ;
98
100
static char * difffilename ;
101
+ static const char * sockdir ;
102
+ #ifdef HAVE_UNIX_SOCKETS
103
+ static const char * temp_sockdir ;
104
+ static char sockself [MAXPGPATH ];
105
+ static char socklock [MAXPGPATH ];
106
+ #endif
99
107
100
108
static _resultmap * resultmap = NULL ;
101
109
@@ -292,6 +300,81 @@ stop_postmaster(void)
292
300
}
293
301
}
294
302
303
+ #ifdef HAVE_UNIX_SOCKETS
304
+ /*
305
+ * Remove the socket temporary directory. pg_regress never waits for a
306
+ * postmaster exit, so it is indeterminate whether the postmaster has yet to
307
+ * unlink the socket and lock file. Unlink them here so we can proceed to
308
+ * remove the directory. Ignore errors; leaking a temporary directory is
309
+ * unimportant. This can run from a signal handler. The code is not
310
+ * acceptable in a Windows signal handler (see initdb.c:trapsig()), but
311
+ * Windows is not a HAVE_UNIX_SOCKETS platform.
312
+ */
313
+ static void
314
+ remove_temp (void )
315
+ {
316
+ unlink (sockself );
317
+ unlink (socklock );
318
+ rmdir (temp_sockdir );
319
+ }
320
+
321
+ /*
322
+ * Signal handler that calls remove_temp() and reraises the signal.
323
+ */
324
+ static void
325
+ signal_remove_temp (int signum )
326
+ {
327
+ remove_temp ();
328
+
329
+ pqsignal (signum , SIG_DFL );
330
+ raise (signum );
331
+ }
332
+
333
+ /*
334
+ * Create a temporary directory suitable for the server's Unix-domain socket.
335
+ * The directory will have mode 0700 or stricter, so no other OS user can open
336
+ * our socket to exploit our use of trust authentication. Most systems
337
+ * constrain the length of socket paths well below _POSIX_PATH_MAX, so we
338
+ * place the directory under /tmp rather than relative to the possibly-deep
339
+ * current working directory.
340
+ *
341
+ * Compared to using the compiled-in DEFAULT_PGSOCKET_DIR, this also permits
342
+ * testing to work in builds that relocate it to a directory not writable to
343
+ * the build/test user.
344
+ */
345
+ static const char *
346
+ make_temp_sockdir (void )
347
+ {
348
+ char * template = strdup ("/tmp/pg_regress-XXXXXX" );
349
+
350
+ temp_sockdir = mkdtemp (template );
351
+ if (temp_sockdir == NULL )
352
+ {
353
+ fprintf (stderr , _ ("%s: could not create directory \"%s\": %s\n" ),
354
+ progname , template , strerror (errno ));
355
+ exit (2 );
356
+ }
357
+
358
+ /* Stage file names for remove_temp(). Unsafe in a signal handler. */
359
+ UNIXSOCK_PATH (sockself , port , temp_sockdir );
360
+ snprintf (socklock , sizeof (socklock ), "%s.lock" , sockself );
361
+
362
+ /* Remove the directory during clean exit. */
363
+ atexit (remove_temp );
364
+
365
+ /*
366
+ * Remove the directory before dying to the usual signals. Omit SIGQUIT,
367
+ * preserving it as a quick, untidy exit.
368
+ */
369
+ pqsignal (SIGHUP , signal_remove_temp );
370
+ pqsignal (SIGINT , signal_remove_temp );
371
+ pqsignal (SIGPIPE , signal_remove_temp );
372
+ pqsignal (SIGTERM , signal_remove_temp );
373
+
374
+ return temp_sockdir ;
375
+ }
376
+ #endif /* HAVE_UNIX_SOCKETS */
377
+
295
378
/*
296
379
* Always exit through here, not through plain exit(), to ensure we make
297
380
* an effort to shut down a temp postmaster
@@ -753,8 +836,7 @@ initialize_environment(void)
753
836
* the wrong postmaster, or otherwise behave in nondefault ways. (Note
754
837
* we also use psql's -X switch consistently, so that ~/.psqlrc files
755
838
* won't mess things up.) Also, set PGPORT to the temp port, and set
756
- * or unset PGHOST depending on whether we are using TCP or Unix
757
- * sockets.
839
+ * PGHOST depending on whether we are using TCP or Unix sockets.
758
840
*/
759
841
unsetenv ("PGDATABASE" );
760
842
unsetenv ("PGUSER" );
@@ -763,10 +845,19 @@ initialize_environment(void)
763
845
unsetenv ("PGREQUIRESSL" );
764
846
unsetenv ("PGCONNECT_TIMEOUT" );
765
847
unsetenv ("PGDATA" );
848
+ #ifdef HAVE_UNIX_SOCKETS
766
849
if (hostname != NULL )
767
850
doputenv ("PGHOST" , hostname );
768
851
else
769
- unsetenv ("PGHOST" );
852
+ {
853
+ sockdir = getenv ("PG_REGRESS_SOCK_DIR" );
854
+ if (!sockdir )
855
+ sockdir = make_temp_sockdir ();
856
+ doputenv ("PGHOST" , sockdir );
857
+ }
858
+ #else
859
+ doputenv ("PGHOST" , hostname );
860
+ #endif
770
861
unsetenv ("PGHOSTADDR" );
771
862
if (port != -1 )
772
863
{
@@ -2035,7 +2126,9 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2035
2126
/*
2036
2127
* To reduce chances of interference with parallel installations, use
2037
2128
* a port number starting in the private range (49152-65535)
2038
- * calculated from the version number.
2129
+ * calculated from the version number. This aids !HAVE_UNIX_SOCKETS
2130
+ * systems; elsewhere, the use of a private socket directory already
2131
+ * prevents interference.
2039
2132
*/
2040
2133
port = 0xC000 | (PG_VERSION_NUM & 0x3FFF );
2041
2134
@@ -2185,10 +2278,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2185
2278
*/
2186
2279
header (_ ("starting postmaster" ));
2187
2280
snprintf (buf , sizeof (buf ),
2188
- SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE ,
2189
- bindir , temp_install ,
2190
- debug ? " -d 5" : "" ,
2191
- hostname ? hostname : "" ,
2281
+ SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s "
2282
+ "-c \"listen_addresses=%s\" -k \"%s\" "
2283
+ "> \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE ,
2284
+ bindir , temp_install , debug ? " -d 5" : "" ,
2285
+ hostname ? hostname : "" , sockdir ? sockdir : "" ,
2192
2286
outputdir );
2193
2287
postmaster_pid = spawn_process (buf );
2194
2288
if (postmaster_pid == INVALID_PID )
0 commit comments