@@ -141,7 +141,6 @@ static bool postmaster_is_alive(pid_t pid);
141
141
142
142
static char postopts_file [MAXPGPATH ];
143
143
static char pid_file [MAXPGPATH ];
144
- static char conf_file [MAXPGPATH ];
145
144
static char backup_file [MAXPGPATH ];
146
145
static char recovery_file [MAXPGPATH ];
147
146
@@ -404,113 +403,108 @@ start_postmaster(void)
404
403
static PGPing
405
404
test_postmaster_connection (bool do_checkpoint )
406
405
{
406
+ int portnum = 0 ;
407
+ char socket_dir [MAXPGPATH ];
408
+ char connstr [MAXPGPATH + 256 ];
407
409
PGPing ret = PQPING_OK ; /* assume success for wait == zero */
410
+ char * * optlines ;
408
411
int i ;
409
- char portstr [32 ];
410
- char * p ;
411
- char * q ;
412
- char connstr [128 ]; /* Should be way more than enough! */
413
412
414
- portstr [0 ] = '\0' ;
415
-
416
- /*
417
- * Look in post_opts for a -p switch.
418
- *
419
- * This parsing code is not amazingly bright; it could for instance get
420
- * fooled if ' -p' occurs within a quoted argument value. Given that few
421
- * people pass complicated settings in post_opts, it's probably good
422
- * enough.
423
- */
424
- for (p = post_opts ; * p ;)
413
+ socket_dir [0 ] = '\0' ;
414
+ connstr [0 ] = '\0' ;
415
+
416
+ for (i = 0 ; i < wait_seconds ; i ++ )
425
417
{
426
- /* advance past whitespace */
427
- while (isspace ((unsigned char ) * p ))
428
- p ++ ;
429
-
430
- if (strncmp (p , "-p" , 2 ) == 0 )
418
+ /* Do we need a connection string? */
419
+ if (connstr [0 ] == '\0' )
431
420
{
432
- p += 2 ;
433
- /* advance past any whitespace/quoting */
434
- while (isspace ((unsigned char ) * p ) || * p == '\'' || * p == '"' )
435
- p ++ ;
436
- /* find end of value (not including any ending quote!) */
437
- q = p ;
438
- while (* q &&
439
- !(isspace ((unsigned char ) * q ) || * q == '\'' || * q == '"' ))
440
- q ++ ;
441
- /* and save the argument value */
442
- strlcpy (portstr , p , Min ((q - p ) + 1 , sizeof (portstr )));
443
- /* keep looking, maybe there is another -p */
444
- p = q ;
445
- }
446
- /* Advance to next whitespace */
447
- while (* p && !isspace ((unsigned char ) * p ))
448
- p ++ ;
449
- }
421
+ /*
422
+ * The number of lines in postmaster.pid tells us several things:
423
+ *
424
+ * # of lines
425
+ * 0 lock file created but status not written
426
+ * 2 pre-9.1 server, shared memory not created
427
+ * 3 pre-9.1 server, shared memory created
428
+ * 4 9.1+ server, shared memory not created
429
+ * 5 9.1+ server, shared memory created
430
+ *
431
+ * For pre-9.1 Unix servers, we grab the port number from the
432
+ * shmem key (first value on line 3). Pre-9.1 Win32 has no
433
+ * written shmem key, so we fail. 9.1+ writes both the port
434
+ * number and socket address in the file for us to use.
435
+ * (PG_VERSION could also have told us the major version.)
436
+ */
437
+
438
+ /* Try to read a completed postmaster.pid file */
439
+ if ((optlines = readfile (pid_file )) != NULL &&
440
+ optlines [0 ] != NULL &&
441
+ optlines [1 ] != NULL &&
442
+ optlines [2 ] != NULL )
443
+ {
444
+ /* A 3-line file? */
445
+ if (optlines [3 ] == NULL )
446
+ {
447
+ /*
448
+ * Pre-9.1: on Unix, we get the port number by
449
+ * deriving it from the shmem key (the first number on
450
+ * on the line); see
451
+ * miscinit.c::RecordSharedMemoryInLockFile().
452
+ */
453
+ portnum = atoi (optlines [2 ]) / 1000 ;
454
+ /* Win32 does not give us a shmem key, so we fail. */
455
+ if (portnum == 0 )
456
+ {
457
+ write_stderr (_ ("%s: -w option is not supported on this platform\nwhen connecting to a pre-9.1 server\n" ),
458
+ progname );
459
+ return PQPING_NO_ATTEMPT ;
460
+ }
461
+ }
462
+ else /* 9.1+ server */
463
+ {
464
+ portnum = atoi (optlines [2 ]);
465
+
466
+ /* Get socket directory, if specified. */
467
+ if (optlines [3 ][0 ] != '\n' )
468
+ {
469
+ /*
470
+ * While unix_socket_directory can accept relative
471
+ * directories, libpq's host must have a leading slash
472
+ * to indicate a socket directory.
473
+ */
474
+ if (optlines [3 ][0 ] != '/' )
475
+ {
476
+ write_stderr (_ ("%s: -w option cannot use a relative socket directory specification\n" ),
477
+ progname );
478
+ return PQPING_NO_ATTEMPT ;
479
+ }
480
+ strlcpy (socket_dir , optlines [3 ], MAXPGPATH );
481
+ /* remove newline */
482
+ if (strchr (socket_dir , '\n' ) != NULL )
483
+ * strchr (socket_dir , '\n' ) = '\0' ;
484
+ }
485
+ }
450
486
451
- /*
452
- * Search config file for a 'port' option.
453
- *
454
- * This parsing code isn't amazingly bright either, but it should be okay
455
- * for valid port settings.
456
- */
457
- if (!portstr [0 ])
458
- {
459
- char * * optlines ;
487
+ /*
488
+ * We need to set connect_timeout otherwise on Windows the
489
+ * Service Control Manager (SCM) will probably timeout first.
490
+ */
491
+ snprintf (connstr , sizeof (connstr ),
492
+ "dbname=postgres port=%d connect_timeout=5" , portnum );
460
493
461
- optlines = readfile (conf_file );
462
- if (optlines != NULL )
463
- {
464
- for (; * optlines != NULL ; optlines ++ )
465
- {
466
- p = * optlines ;
467
-
468
- while (isspace ((unsigned char ) * p ))
469
- p ++ ;
470
- if (strncmp (p , "port" , 4 ) != 0 )
471
- continue ;
472
- p += 4 ;
473
- while (isspace ((unsigned char ) * p ))
474
- p ++ ;
475
- if (* p != '=' )
476
- continue ;
477
- p ++ ;
478
- /* advance past any whitespace/quoting */
479
- while (isspace ((unsigned char ) * p ) || * p == '\'' || * p == '"' )
480
- p ++ ;
481
- /* find end of value (not including any ending quote/comment!) */
482
- q = p ;
483
- while (* q &&
484
- !(isspace ((unsigned char ) * q ) ||
485
- * q == '\'' || * q == '"' || * q == '#' ))
486
- q ++ ;
487
- /* and save the argument value */
488
- strlcpy (portstr , p , Min ((q - p ) + 1 , sizeof (portstr )));
489
- /* keep looking, maybe there is another */
494
+ if (socket_dir [0 ] != '\0' )
495
+ snprintf (connstr + strlen (connstr ), sizeof (connstr ) - strlen (connstr ),
496
+ " host='%s'" , socket_dir );
490
497
}
491
498
}
492
- }
493
499
494
- /* Check environment */
495
- if (!portstr [0 ] && getenv ("PGPORT" ) != NULL )
496
- strlcpy (portstr , getenv ("PGPORT" ), sizeof (portstr ));
497
-
498
- /* Else use compiled-in default */
499
- if (!portstr [0 ])
500
- snprintf (portstr , sizeof (portstr ), "%d" , DEF_PGPORT );
501
-
502
- /*
503
- * We need to set a connect timeout otherwise on Windows the SCM will
504
- * probably timeout first
505
- */
506
- snprintf (connstr , sizeof (connstr ),
507
- "dbname=postgres port=%s connect_timeout=5" , portstr );
500
+ /* If we have a connection string, ping the server */
501
+ if (connstr [0 ] != '\0' )
502
+ {
503
+ ret = PQping (connstr );
504
+ if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT )
505
+ break ;
506
+ }
508
507
509
- for (i = 0 ; i < wait_seconds ; i ++ )
510
- {
511
- ret = PQping (connstr );
512
- if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT )
513
- break ;
514
508
/* No response, or startup still in process; wait */
515
509
#if defined(WIN32 )
516
510
if (do_checkpoint )
@@ -2009,7 +2003,6 @@ main(int argc, char **argv)
2009
2003
{
2010
2004
snprintf (postopts_file , MAXPGPATH , "%s /postmaster .opts ", pg_data );
2011
2005
snprintf (pid_file , MAXPGPATH , "%s /postmaster .pid ", pg_data );
2012
- snprintf (conf_file , MAXPGPATH , "%s /postgresql .conf ", pg_data );
2013
2006
snprintf (backup_file , MAXPGPATH , "%s /backup_label ", pg_data );
2014
2007
snprintf (recovery_file , MAXPGPATH , "%s /recovery .conf ", pg_data );
2015
2008
}
0 commit comments