@@ -141,7 +141,6 @@ static bool postmaster_is_alive(pid_t pid);
141141
142142static char postopts_file [MAXPGPATH ];
143143static char pid_file [MAXPGPATH ];
144- static char conf_file [MAXPGPATH ];
145144static char backup_file [MAXPGPATH ];
146145static char recovery_file [MAXPGPATH ];
147146
@@ -404,113 +403,108 @@ start_postmaster(void)
404403static PGPing
405404test_postmaster_connection (bool do_checkpoint )
406405{
406+ int portnum = 0 ;
407+ char socket_dir [MAXPGPATH ];
408+ char connstr [MAXPGPATH + 256 ];
407409 PGPing ret = PQPING_OK ; /* assume success for wait == zero */
410+ char * * optlines ;
408411 int i ;
409- char portstr [32 ];
410- char * p ;
411- char * q ;
412- char connstr [128 ]; /* Should be way more than enough! */
413412
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 ++ )
425417 {
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' )
431420 {
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+ }
450486
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 );
460493
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 );
490497 }
491498 }
492- }
493499
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+ }
508507
509- for (i = 0 ; i < wait_seconds ; i ++ )
510- {
511- ret = PQping (connstr );
512- if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT )
513- break ;
514508 /* No response, or startup still in process; wait */
515509#if defined(WIN32 )
516510 if (do_checkpoint )
@@ -2009,7 +2003,6 @@ main(int argc, char **argv)
20092003 {
20102004 snprintf (postopts_file , MAXPGPATH , "%s /postmaster .opts ", pg_data );
20112005 snprintf (pid_file , MAXPGPATH , "%s /postmaster .pid ", pg_data );
2012- snprintf (conf_file , MAXPGPATH , "%s /postgresql .conf ", pg_data );
20132006 snprintf (backup_file , MAXPGPATH , "%s /backup_label ", pg_data );
20142007 snprintf (recovery_file , MAXPGPATH , "%s /recovery .conf ", pg_data );
20152008 }
0 commit comments