32
32
#include "common/username.h"
33
33
#include "getopt_long.h"
34
34
#include "lib/stringinfo.h"
35
+ #include "libpq-fe.h"
35
36
#include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
36
37
#include "pg_config_paths.h"
37
38
#include "pg_regress.h"
@@ -75,6 +76,12 @@ const char *pretty_diff_opts = "-w -U3";
75
76
*/
76
77
#define TESTNAME_WIDTH 36
77
78
79
+ /*
80
+ * The number times per second that pg_regress checks to see if the test
81
+ * instance server has started and is available for connection.
82
+ */
83
+ #define WAIT_TICKS_PER_SECOND 20
84
+
78
85
typedef enum TAPtype
79
86
{
80
87
DIAG = 0 ,
@@ -107,6 +114,7 @@ static bool nolocale = false;
107
114
static bool use_existing = false;
108
115
static char * hostname = NULL ;
109
116
static int port = -1 ;
117
+ static char portstr [16 ];
110
118
static bool port_specified_by_user = false;
111
119
static char * dlpath = PKGLIBDIR ;
112
120
static char * user = NULL ;
@@ -2107,7 +2115,6 @@ regression_main(int argc, char *argv[],
2107
2115
int i ;
2108
2116
int option_index ;
2109
2117
char buf [MAXPGPATH * 4 ];
2110
- char buf2 [MAXPGPATH * 4 ];
2111
2118
2112
2119
pg_logging_init (argv [0 ]);
2113
2120
progname = get_progname (argv [0 ]);
@@ -2296,6 +2303,9 @@ regression_main(int argc, char *argv[],
2296
2303
const char * env_wait ;
2297
2304
int wait_seconds ;
2298
2305
const char * initdb_template_dir ;
2306
+ const char * keywords [4 ];
2307
+ const char * values [4 ];
2308
+ PGPing rv ;
2299
2309
2300
2310
/*
2301
2311
* Prepare the temp instance
@@ -2436,21 +2446,28 @@ regression_main(int argc, char *argv[],
2436
2446
#endif
2437
2447
2438
2448
/*
2439
- * Check if there is a postmaster running already.
2449
+ * Prepare the connection params for checking the state of the server
2450
+ * before starting the tests.
2440
2451
*/
2441
- snprintf (buf2 , sizeof (buf2 ),
2442
- "\"%s%spsql\" -X postgres <%s 2>%s" ,
2443
- bindir ? bindir : "" ,
2444
- bindir ? "/" : "" ,
2445
- DEVNULL , DEVNULL );
2452
+ sprintf (portstr , "%d" , port );
2453
+ keywords [0 ] = "dbname" ;
2454
+ values [0 ] = "postgres" ;
2455
+ keywords [1 ] = "port" ;
2456
+ values [1 ] = portstr ;
2457
+ keywords [2 ] = "host" ;
2458
+ values [2 ] = hostname ? hostname : sockdir ;
2459
+ keywords [3 ] = NULL ;
2460
+ values [3 ] = NULL ;
2446
2461
2462
+ /*
2463
+ * Check if there is a postmaster running already.
2464
+ */
2447
2465
for (i = 0 ; i < 16 ; i ++ )
2448
2466
{
2449
- fflush (NULL );
2450
- if (system (buf2 ) == 0 )
2451
- {
2452
- char s [16 ];
2467
+ rv = PQpingParams (keywords , values , 1 );
2453
2468
2469
+ if (rv == PQPING_OK )
2470
+ {
2454
2471
if (port_specified_by_user || i == 15 )
2455
2472
{
2456
2473
note ("port %d apparently in use" , port );
@@ -2461,8 +2478,8 @@ regression_main(int argc, char *argv[],
2461
2478
2462
2479
note ("port %d apparently in use, trying %d" , port , port + 1 );
2463
2480
port ++ ;
2464
- sprintf (s , "%d" , port );
2465
- setenv ("PGPORT" , s , 1 );
2481
+ sprintf (portstr , "%d" , port );
2482
+ setenv ("PGPORT" , portstr , 1 );
2466
2483
}
2467
2484
else
2468
2485
break ;
@@ -2485,11 +2502,11 @@ regression_main(int argc, char *argv[],
2485
2502
bail ("could not spawn postmaster: %s" , strerror (errno ));
2486
2503
2487
2504
/*
2488
- * Wait till postmaster is able to accept connections; normally this
2489
- * is only a second or so, but Cygwin is reportedly *much* slower, and
2490
- * test builds using Valgrind or similar tools might be too. Hence,
2491
- * allow the default timeout of 60 seconds to be overridden from the
2492
- * PGCTLTIMEOUT environment variable.
2505
+ * Wait till postmaster is able to accept connections; normally takes
2506
+ * only a fraction of a second or so, but Cygwin is reportedly *much*
2507
+ * slower, and test builds using Valgrind or similar tools might be
2508
+ * too. Hence, allow the default timeout of 60 seconds to be
2509
+ * overridden from the PGCTLTIMEOUT environment variable.
2493
2510
*/
2494
2511
env_wait = getenv ("PGCTLTIMEOUT" );
2495
2512
if (env_wait != NULL )
@@ -2501,13 +2518,24 @@ regression_main(int argc, char *argv[],
2501
2518
else
2502
2519
wait_seconds = 60 ;
2503
2520
2504
- for (i = 0 ; i < wait_seconds ; i ++ )
2521
+ for (i = 0 ; i < wait_seconds * WAIT_TICKS_PER_SECOND ; i ++ )
2505
2522
{
2506
- /* Done if psql succeeds */
2507
- fflush (NULL );
2508
- if (system (buf2 ) == 0 )
2523
+ /*
2524
+ * It's fairly unlikely that the server is responding immediately
2525
+ * so we start with sleeping before checking instead of the other
2526
+ * way around.
2527
+ */
2528
+ pg_usleep (1000000L / WAIT_TICKS_PER_SECOND );
2529
+
2530
+ rv = PQpingParams (keywords , values , 1 );
2531
+
2532
+ /* Done if the server is running and accepts connections */
2533
+ if (rv == PQPING_OK )
2509
2534
break ;
2510
2535
2536
+ if (rv == PQPING_NO_ATTEMPT )
2537
+ bail ("attempting to connect to postmaster failed" );
2538
+
2511
2539
/*
2512
2540
* Fail immediately if postmaster has exited
2513
2541
*/
@@ -2520,10 +2548,8 @@ regression_main(int argc, char *argv[],
2520
2548
bail ("postmaster failed, examine \"%s/log/postmaster.log\" for the reason" ,
2521
2549
outputdir );
2522
2550
}
2523
-
2524
- pg_usleep (1000000L );
2525
2551
}
2526
- if (i >= wait_seconds )
2552
+ if (i >= wait_seconds * WAIT_TICKS_PER_SECOND )
2527
2553
{
2528
2554
diag ("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason" ,
2529
2555
wait_seconds , outputdir );
0 commit comments