@ -30,6 +30,8 @@
# endif
# include "getopt_long.h"
# include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
# include "libpq/pqsignal.h"
# include "pg_config_paths.h"
/* for resultmap we need a list of pairs of strings */
@ -96,6 +98,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 ;
@ -292,6 +300,81 @@ 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 )
{
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 */
/*
* Always exit through here , not through plain exit ( ) , to ensure we make
* an effort to shut down a temp postmaster
@ -753,8 +836,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 " ) ;
@ -763,10 +845,19 @@ 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
doputenv ( " PGHOST " , hostname ) ;
# endif
unsetenv ( " PGHOSTADDR " ) ;
if ( port ! = - 1 )
{
@ -2035,7 +2126,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 ) ;
@ -2185,10 +2278,11 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
*/
header ( _ ( " starting postmaster " ) ) ;
snprintf ( buf , sizeof ( buf ) ,
SYSTEMQUOTE " \" %s/postgres \" -D \" %s/data \" -F%s -c \" listen_addresses=%s \" > \" %s/log/postmaster.log \" 2>&1 " SYSTEMQUOTE ,
bindir , temp_install ,
debug ? " -d 5 " : " " ,
hostname ? hostname : " " ,
SYSTEMQUOTE " \" %s/postgres \" -D \" %s/data \" -F%s "
" -c \" listen_addresses=%s \" -k \" %s \" "
" > \" %s/log/postmaster.log \" 2>&1 " SYSTEMQUOTE ,
bindir , temp_install , debug ? " -d 5 " : " " ,
hostname ? hostname : " " , sockdir ? sockdir : " " ,
outputdir ) ;
postmaster_pid = spawn_process ( buf ) ;
if ( postmaster_pid = = INVALID_PID )