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
* Always exit through here, not through plain exit(), to ensure we make
312
395
* an effort to shut down a temp postmaster
@@ -768,8 +851,7 @@ initialize_environment(void)
768
851
* the wrong postmaster, or otherwise behave in nondefault ways. (Note
769
852
* we also use psql's -X switch consistently, so that ~/.psqlrc files
770
853
* won't mess things up.) Also, set PGPORT to the temp port, and set
771
- * or unset PGHOST depending on whether we are using TCP or Unix
772
- * sockets.
854
+ * PGHOST depending on whether we are using TCP or Unix sockets.
773
855
*/
774
856
unsetenv ("PGDATABASE" );
775
857
unsetenv ("PGUSER" );
@@ -778,10 +860,19 @@ initialize_environment(void)
778
860
unsetenv ("PGREQUIRESSL" );
779
861
unsetenv ("PGCONNECT_TIMEOUT" );
780
862
unsetenv ("PGDATA" );
863
+ #ifdef HAVE_UNIX_SOCKETS
781
864
if (hostname != NULL )
782
865
doputenv ("PGHOST" , hostname );
783
866
else
784
- unsetenv ("PGHOST" );
867
+ {
868
+ sockdir = getenv ("PG_REGRESS_SOCK_DIR" );
869
+ if (!sockdir )
870
+ sockdir = make_temp_sockdir ();
871
+ doputenv ("PGHOST" , sockdir );
872
+ }
873
+ #else
874
+ doputenv ("PGHOST" , hostname );
875
+ #endif
785
876
unsetenv ("PGHOSTADDR" );
786
877
if (port != -1 )
787
878
{
@@ -2084,7 +2175,9 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2084
2175
/*
2085
2176
* To reduce chances of interference with parallel installations, use
2086
2177
* a port number starting in the private range (49152-65535)
2087
- * calculated from the version number.
2178
+ * calculated from the version number. This aids !HAVE_UNIX_SOCKETS
2179
+ * systems; elsewhere, the use of a private socket directory already
2180
+ * prevents interference.
2088
2181
*/
2089
2182
port = 0xC000 | (PG_VERSION_NUM & 0x3FFF );
2090
2183
@@ -2253,10 +2346,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2253
2346
*/
2254
2347
header (_ ("starting postmaster" ));
2255
2348
snprintf (buf , sizeof (buf ),
2256
- SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s -c \"listen_addresses=%s\" > \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE ,
2257
- bindir , temp_install ,
2258
- debug ? " -d 5" : "" ,
2259
- hostname ? hostname : "" ,
2349
+ SYSTEMQUOTE "\"%s/postgres\" -D \"%s/data\" -F%s "
2350
+ "-c \"listen_addresses=%s\" -k \"%s\" "
2351
+ "> \"%s/log/postmaster.log\" 2>&1" SYSTEMQUOTE ,
2352
+ bindir , temp_install , debug ? " -d 5" : "" ,
2353
+ hostname ? hostname : "" , sockdir ? sockdir : "" ,
2260
2354
outputdir );
2261
2355
postmaster_pid = spawn_process (buf );
2262
2356
if (postmaster_pid == INVALID_PID )
0 commit comments