Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Typedefs | Enumerations | Functions | Variables

pg_ctl.c File Reference

#include "postgres_fe.h"
#include "libpq-fe.h"
#include <fcntl.h>
#include <locale.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "getopt_long.h"
#include "miscadmin.h"
Include dependency graph for pg_ctl.c:

Go to the source code of this file.

Defines

#define DEFAULT_WAIT   60

Typedefs

typedef long pgpid_t

Enumerations

enum  ShutdownMode { SMART_MODE, FAST_MODE, IMMEDIATE_MODE }
enum  CtlCommand {
  NO_COMMAND = 0, INIT_COMMAND, START_COMMAND, STOP_COMMAND,
  RESTART_COMMAND, RELOAD_COMMAND, STATUS_COMMAND, PROMOTE_COMMAND,
  KILL_COMMAND, REGISTER_COMMAND, UNREGISTER_COMMAND, RUN_AS_SERVICE_COMMAND
}

Functions

static void write_stderr (const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE
static void static void do_advice (void)
static void do_help (void)
static void set_mode (char *modeopt)
static void set_sig (char *signame)
static void do_init (void)
static void do_start (void)
static void do_stop (void)
static void do_restart (void)
static void do_reload (void)
static void do_status (void)
static void do_promote (void)
static void do_kill (pgpid_t pid)
static void print_msg (const char *msg)
static void adjust_data_dir (void)
static pgpid_t get_pgpid (void)
static char ** readfile (const char *path)
static int start_postmaster (void)
static void read_post_opts (void)
static PGPing test_postmaster_connection (bool)
static bool postmaster_is_alive (pid_t pid)
static char * find_other_exec_or_die (const char *argv0, const char *target, const char *versionstr)
int main (int argc, char **argv)

Variables

static bool do_wait = false
static bool wait_set = false
static int wait_seconds = DEFAULT_WAIT
static bool silent_mode = false
static ShutdownMode shutdown_mode = SMART_MODE
static int sig = SIGTERM
static CtlCommand ctl_command = NO_COMMAND
static char * pg_data = NULL
static char * pg_config = NULL
static char * pgdata_opt = NULL
static char * post_opts = NULL
static const char * progname
static char * log_file = NULL
static char * exec_path = NULL
static char * register_servicename = "PostgreSQL"
static char * register_username = NULL
static char * register_password = NULL
static char * argv0 = NULL
static bool allow_core_files = false
static time_t start_time
static char postopts_file [MAXPGPATH]
static char pid_file [MAXPGPATH]
static char backup_file [MAXPGPATH]
static char recovery_file [MAXPGPATH]
static char promote_file [MAXPGPATH]

Define Documentation

#define DEFAULT_WAIT   60

Definition at line 74 of file pg_ctl.c.


Typedef Documentation

typedef long pgpid_t

Definition at line 47 of file pg_ctl.c.


Enumeration Type Documentation

enum CtlCommand
Enumerator:
NO_COMMAND 
INIT_COMMAND 
START_COMMAND 
STOP_COMMAND 
RESTART_COMMAND 
RELOAD_COMMAND 
STATUS_COMMAND 
PROMOTE_COMMAND 
KILL_COMMAND 
REGISTER_COMMAND 
UNREGISTER_COMMAND 
RUN_AS_SERVICE_COMMAND 

Definition at line 58 of file pg_ctl.c.

{
    NO_COMMAND = 0,
    INIT_COMMAND,
    START_COMMAND,
    STOP_COMMAND,
    RESTART_COMMAND,
    RELOAD_COMMAND,
    STATUS_COMMAND,
    PROMOTE_COMMAND,
    KILL_COMMAND,
    REGISTER_COMMAND,
    UNREGISTER_COMMAND,
    RUN_AS_SERVICE_COMMAND
} CtlCommand;

Enumerator:
SMART_MODE 
FAST_MODE 
IMMEDIATE_MODE 

Definition at line 50 of file pg_ctl.c.

{
    SMART_MODE,
    FAST_MODE,
    IMMEDIATE_MODE
} ShutdownMode;


Function Documentation

static void adjust_data_dir ( void   )  [static]

Definition at line 1910 of file pg_ctl.c.

References _, argv0, canonicalize_path(), exec_path, filename, find_other_exec_or_die(), free, MAXPGPATH, my_exec_path, NULL, PG_BACKEND_VERSIONSTR, pg_config, pg_data, pg_strdup(), pgdata_opt, post_opts, progname, snprintf(), SYSTEMQUOTE, and write_stderr.

{
    char        cmd[MAXPGPATH],
                filename[MAXPGPATH],
               *my_exec_path;
    FILE       *fd;

    /* do nothing if we're working without knowledge of data dir */
    if (pg_config == NULL)
        return;

    /* If there is no postgresql.conf, it can't be a config-only dir */
    snprintf(filename, sizeof(filename), "%s/postgresql.conf", pg_config);
    if ((fd = fopen(filename, "r")) == NULL)
        return;
    fclose(fd);

    /* If PG_VERSION exists, it can't be a config-only dir */
    snprintf(filename, sizeof(filename), "%s/PG_VERSION", pg_config);
    if ((fd = fopen(filename, "r")) != NULL)
    {
        fclose(fd);
        return;
    }

    /* Must be a configuration directory, so find the data directory */

    /* we use a private my_exec_path to avoid interfering with later uses */
    if (exec_path == NULL)
        my_exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);
    else
        my_exec_path = pg_strdup(exec_path);

    snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s -C data_directory" SYSTEMQUOTE,
             my_exec_path, pgdata_opt ? pgdata_opt : "", post_opts ?
             post_opts : "");

    fd = popen(cmd, "r");
    if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL)
    {
        write_stderr(_("%s: could not determine the data directory using command \"%s\"\n"), progname, cmd);
        exit(1);
    }
    pclose(fd);
    free(my_exec_path);

    /* Remove trailing newline */
    if (strchr(filename, '\n') != NULL)
        *strchr(filename, '\n') = '\0';

    free(pg_data);
    pg_data = pg_strdup(filename);
    canonicalize_path(pg_data);
}

static void do_advice ( void   )  [static]

Definition at line 1752 of file pg_ctl.c.

References _, progname, and write_stderr.

Referenced by main(), set_mode(), and set_sig().

{
    write_stderr(_("Try \"%s --help\" for more information.\n"), progname);
}

static void do_help ( void   )  [static]

Definition at line 1760 of file pg_ctl.c.

References _, and progname.

Referenced by main().

{
    printf(_("%s is a utility to initialize, start, stop, or control a PostgreSQL server.\n\n"), progname);
    printf(_("Usage:\n"));
    printf(_("  %s init[db]               [-D DATADIR] [-s] [-o \"OPTIONS\"]\n"), progname);
    printf(_("  %s start   [-w] [-t SECS] [-D DATADIR] [-s] [-l FILENAME] [-o \"OPTIONS\"]\n"), progname);
    printf(_("  %s stop    [-W] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"), progname);
    printf(_("  %s restart [-w] [-t SECS] [-D DATADIR] [-s] [-m SHUTDOWN-MODE]\n"
             "                 [-o \"OPTIONS\"]\n"), progname);
    printf(_("  %s reload  [-D DATADIR] [-s]\n"), progname);
    printf(_("  %s status  [-D DATADIR]\n"), progname);
    printf(_("  %s promote [-D DATADIR] [-s]\n"), progname);
    printf(_("  %s kill    SIGNALNAME PID\n"), progname);
#if defined(WIN32) || defined(__CYGWIN__)
    printf(_("  %s register   [-N SERVICENAME] [-U USERNAME] [-P PASSWORD] [-D DATADIR]\n"
             "                    [-S START-TYPE] [-w] [-t SECS] [-o \"OPTIONS\"]\n"), progname);
    printf(_("  %s unregister [-N SERVICENAME]\n"), progname);
#endif

    printf(_("\nCommon options:\n"));
    printf(_("  -D, --pgdata=DATADIR   location of the database storage area\n"));
    printf(_("  -s, --silent           only print errors, no informational messages\n"));
    printf(_("  -t, --timeout=SECS     seconds to wait when using -w option\n"));
    printf(_("  -V, --version          output version information, then exit\n"));
    printf(_("  -w                     wait until operation completes\n"));
    printf(_("  -W                     do not wait until operation completes\n"));
    printf(_("  -?, --help             show this help, then exit\n"));
    printf(_("(The default is to wait for shutdown, but not for start or restart.)\n\n"));
    printf(_("If the -D option is omitted, the environment variable PGDATA is used.\n"));

    printf(_("\nOptions for start or restart:\n"));
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
    printf(_("  -c, --core-files       allow postgres to produce core files\n"));
#else
    printf(_("  -c, --core-files       not applicable on this platform\n"));
#endif
    printf(_("  -l, --log=FILENAME     write (or append) server log to FILENAME\n"));
    printf(_("  -o OPTIONS             command line options to pass to postgres\n"
     "                         (PostgreSQL server executable) or initdb\n"));
    printf(_("  -p PATH-TO-POSTGRES    normally not necessary\n"));
    printf(_("\nOptions for stop, restart, or promote:\n"));
    printf(_("  -m, --mode=MODE        MODE can be \"smart\", \"fast\", or \"immediate\"\n"));

    printf(_("\nShutdown modes are:\n"));
    printf(_("  smart       quit after all clients have disconnected\n"));
    printf(_("  fast        quit directly, with proper shutdown\n"));
    printf(_("  immediate   quit without complete shutdown; will lead to recovery on restart\n"));

    printf(_("\nAllowed signal names for kill:\n"));
    printf("  ABRT HUP INT QUIT TERM USR1 USR2\n");

#if defined(WIN32) || defined(__CYGWIN__)
    printf(_("\nOptions for register and unregister:\n"));
    printf(_("  -N SERVICENAME  service name with which to register PostgreSQL server\n"));
    printf(_("  -P PASSWORD     password of account to register PostgreSQL server\n"));
    printf(_("  -U USERNAME     user name of account to register PostgreSQL server\n"));
    printf(_("  -S START-TYPE   service start type to register PostgreSQL server\n"));

    printf(_("\nStart types are:\n"));
    printf(_("  auto       start service automatically during system startup (default)\n"));
    printf(_("  demand     start service on demand\n"));
#endif

    printf(_("\nReport bugs to <[email protected]>.\n"));
}

static void do_init ( void   )  [static]

Definition at line 739 of file pg_ctl.c.

References _, argv0, DEVNULL, exec_path, find_other_exec_or_die(), MAXPGPATH, NULL, pgdata_opt, post_opts, progname, silent_mode, snprintf(), system(), SYSTEMQUOTE, and write_stderr.

Referenced by main().

{
    char        cmd[MAXPGPATH];

    if (exec_path == NULL)
        exec_path = find_other_exec_or_die(argv0, "initdb", "initdb (PostgreSQL) " PG_VERSION "\n");

    if (pgdata_opt == NULL)
        pgdata_opt = "";

    if (post_opts == NULL)
        post_opts = "";

    if (!silent_mode)
        snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s" SYSTEMQUOTE,
                 exec_path, pgdata_opt, post_opts);
    else
        snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s > \"%s\"" SYSTEMQUOTE,
                 exec_path, pgdata_opt, post_opts, DEVNULL);

    if (system(cmd) != 0)
    {
        write_stderr(_("%s: database system initialization failed\n"), progname);
        exit(1);
    }
}

static void do_kill ( pgpid_t  pid  )  [static]

Definition at line 1216 of file pg_ctl.c.

References _, progname, sig, strerror(), and write_stderr.

Referenced by main().

{
    if (kill((pid_t) pid, sig) != 0)
    {
        write_stderr(_("%s: could not send signal %d (PID: %ld): %s\n"),
                     progname, sig, pid, strerror(errno));
        exit(1);
    }
}

static void do_promote ( void   )  [static]

Definition at line 1068 of file pg_ctl.c.

References _, get_pgpid(), MAXPGPATH, NULL, pg_data, pid_file, print_msg(), progname, promote_file, recovery_file, sig, snprintf(), strerror(), unlink(), and write_stderr.

Referenced by main().

{
    FILE       *prmfile;
    pgpid_t     pid;
    struct stat statbuf;

    pid = get_pgpid();

    if (pid == 0)               /* no pid file */
    {
        write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
        write_stderr(_("Is server running?\n"));
        exit(1);
    }
    else if (pid < 0)           /* standalone backend, not postmaster */
    {
        pid = -pid;
        write_stderr(_("%s: cannot promote server; "
                       "single-user server is running (PID: %ld)\n"),
                     progname, pid);
        exit(1);
    }

    /* If recovery.conf doesn't exist, the server is not in standby mode */
    if (stat(recovery_file, &statbuf) != 0)
    {
        write_stderr(_("%s: cannot promote server; "
                       "server is not in standby mode\n"),
                     progname);
        exit(1);
    }

    /*
     * For 9.3 onwards, use fast promotion as the default option.
     * Promotion with a full checkpoint is still possible by writing
     * a file called "promote", e.g.
     *   snprintf(promote_file, MAXPGPATH, "%s/promote", pg_data);
     */
    snprintf(promote_file, MAXPGPATH, "%s/fast_promote", pg_data);

    if ((prmfile = fopen(promote_file, "w")) == NULL)
    {
        write_stderr(_("%s: could not create promote signal file \"%s\": %s\n"),
                     progname, promote_file, strerror(errno));
        exit(1);
    }
    if (fclose(prmfile))
    {
        write_stderr(_("%s: could not write promote signal file \"%s\": %s\n"),
                     progname, promote_file, strerror(errno));
        exit(1);
    }

    sig = SIGUSR1;
    if (kill((pid_t) pid, sig) != 0)
    {
        write_stderr(_("%s: could not send promote signal (PID: %ld): %s\n"),
                     progname, pid, strerror(errno));
        if (unlink(promote_file) != 0)
            write_stderr(_("%s: could not remove promote signal file \"%s\": %s\n"),
                         progname, promote_file, strerror(errno));
        exit(1);
    }

    print_msg(_("server promoting\n"));
}

static void do_reload ( void   )  [static]

Definition at line 1031 of file pg_ctl.c.

References _, get_pgpid(), pid_file, print_msg(), progname, sig, strerror(), and write_stderr.

Referenced by main().

{
    pgpid_t     pid;

    pid = get_pgpid();
    if (pid == 0)               /* no pid file */
    {
        write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
        write_stderr(_("Is server running?\n"));
        exit(1);
    }
    else if (pid < 0)           /* standalone backend, not postmaster */
    {
        pid = -pid;
        write_stderr(_("%s: cannot reload server; "
                       "single-user server is running (PID: %ld)\n"),
                     progname, pid);
        write_stderr(_("Please terminate the single-user server and try again.\n"));
        exit(1);
    }

    if (kill((pid_t) pid, sig) != 0)
    {
        write_stderr(_("%s: could not send reload signal (PID: %ld): %s\n"),
                     progname, pid, strerror(errno));
        exit(1);
    }

    print_msg(_("server signaled\n"));
}

static void do_restart ( void   )  [static]

Definition at line 938 of file pg_ctl.c.

References _, backup_file, do_start(), get_pgpid(), pg_usleep(), pid_file, postmaster_is_alive(), print_msg(), progname, recovery_file, shutdown_mode, sig, SMART_MODE, strerror(), wait_seconds, and write_stderr.

Referenced by main().

{
    int         cnt;
    pgpid_t     pid;
    struct stat statbuf;

    pid = get_pgpid();

    if (pid == 0)               /* no pid file */
    {
        write_stderr(_("%s: PID file \"%s\" does not exist\n"),
                     progname, pid_file);
        write_stderr(_("Is server running?\n"));
        write_stderr(_("starting server anyway\n"));
        do_start();
        return;
    }
    else if (pid < 0)           /* standalone backend, not postmaster */
    {
        pid = -pid;
        if (postmaster_is_alive((pid_t) pid))
        {
            write_stderr(_("%s: cannot restart server; "
                           "single-user server is running (PID: %ld)\n"),
                         progname, pid);
            write_stderr(_("Please terminate the single-user server and try again.\n"));
            exit(1);
        }
    }

    if (postmaster_is_alive((pid_t) pid))
    {
        if (kill((pid_t) pid, sig) != 0)
        {
            write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid,
                         strerror(errno));
            exit(1);
        }

        /*
         * If backup_label exists, an online backup is running. Warn the user
         * that smart shutdown will wait for it to finish. However, if
         * recovery.conf is also present, we're recovering from an online
         * backup instead of performing one.
         */
        if (shutdown_mode == SMART_MODE &&
            stat(backup_file, &statbuf) == 0 &&
            stat(recovery_file, &statbuf) != 0)
        {
            print_msg(_("WARNING: online backup mode is active\n"
                        "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
        }

        print_msg(_("waiting for server to shut down..."));

        /* always wait for restart */

        for (cnt = 0; cnt < wait_seconds; cnt++)
        {
            if ((pid = get_pgpid()) != 0)
            {
                print_msg(".");
                pg_usleep(1000000);     /* 1 sec */
            }
            else
                break;
        }

        if (pid != 0)           /* pid file still exists */
        {
            print_msg(_(" failed\n"));

            write_stderr(_("%s: server does not shut down\n"), progname);
            if (shutdown_mode == SMART_MODE)
                write_stderr(_("HINT: The \"-m fast\" option immediately disconnects sessions rather than\n"
                          "waiting for session-initiated disconnection.\n"));
            exit(1);
        }

        print_msg(_(" done\n"));
        print_msg(_("server stopped\n"));
    }
    else
    {
        write_stderr(_("%s: old server process (PID: %ld) seems to be gone\n"),
                     progname, pid);
        write_stderr(_("starting server anyway\n"));
    }

    do_start();
}

static void do_start ( void   )  [static]

Definition at line 767 of file pg_ctl.c.

References _, allow_core_files, argv0, ctl_command, do_wait, exec_path, find_other_exec_or_die(), get_pgpid(), NULL, PG_BACKEND_VERSIONSTR, pgdata_opt, PQPING_NO_ATTEMPT, PQPING_NO_RESPONSE, PQPING_OK, PQPING_REJECT, print_msg(), progname, putenv, read_post_opts(), RESTART_COMMAND, snprintf(), start_postmaster(), test_postmaster_connection(), and write_stderr.

Referenced by do_restart(), and main().

{
    pgpid_t     old_pid = 0;
    int         exitcode;

    if (ctl_command != RESTART_COMMAND)
    {
        old_pid = get_pgpid();
        if (old_pid != 0)
            write_stderr(_("%s: another server might be running; "
                           "trying to start server anyway\n"),
                         progname);
    }

    read_post_opts();

    /* No -D or -D already added during server start */
    if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
        pgdata_opt = "";

    if (exec_path == NULL)
        exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);

#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
    if (allow_core_files)
        unlimit_core_size();
#endif

    /*
     * If possible, tell the postmaster our parent shell's PID (see the
     * comments in CreateLockFile() for motivation).  Windows hasn't got
     * getppid() unfortunately.
     */
#ifndef WIN32
    {
        static char env_var[32];

        snprintf(env_var, sizeof(env_var), "PG_GRANDPARENT_PID=%d",
                 (int) getppid());
        putenv(env_var);
    }
#endif

    exitcode = start_postmaster();
    if (exitcode != 0)
    {
        write_stderr(_("%s: could not start server: exit code was %d\n"),
                     progname, exitcode);
        exit(1);
    }

    if (do_wait)
    {
        print_msg(_("waiting for server to start..."));

        switch (test_postmaster_connection(false))
        {
            case PQPING_OK:
                print_msg(_(" done\n"));
                print_msg(_("server started\n"));
                break;
            case PQPING_REJECT:
                print_msg(_(" stopped waiting\n"));
                print_msg(_("server is still starting up\n"));
                break;
            case PQPING_NO_RESPONSE:
                print_msg(_(" stopped waiting\n"));
                write_stderr(_("%s: could not start server\n"
                               "Examine the log output.\n"),
                             progname);
                exit(1);
                break;
            case PQPING_NO_ATTEMPT:
                print_msg(_(" failed\n"));
                write_stderr(_("%s: could not wait for server because of misconfiguration\n"),
                             progname);
                exit(1);
        }
    }
    else
        print_msg(_("server starting\n"));
}

static void do_status ( void   )  [static]

Definition at line 1165 of file pg_ctl.c.

References _, get_pgpid(), NULL, postmaster_is_alive(), postopts_file, progname, and readfile().

Referenced by main().

{
    pgpid_t     pid;

    pid = get_pgpid();
    /* Is there a pid file? */
    if (pid != 0)
    {
        /* standalone backend? */
        if (pid < 0)
        {
            pid = -pid;
            if (postmaster_is_alive((pid_t) pid))
            {
                printf(_("%s: single-user server is running (PID: %ld)\n"),
                       progname, pid);
                return;
            }
        }
        else
            /* must be a postmaster */
        {
            if (postmaster_is_alive((pid_t) pid))
            {
                char      **optlines;

                printf(_("%s: server is running (PID: %ld)\n"),
                       progname, pid);

                optlines = readfile(postopts_file);
                if (optlines != NULL)
                    for (; *optlines != NULL; optlines++)
                        fputs(*optlines, stdout);
                return;
            }
        }
    }
    printf(_("%s: no server running\n"), progname);

    /*
     * The Linux Standard Base Core Specification 3.1 says this should return
     * '3'
     * http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-ge
     * neric/iniscrptact.html
     */
    exit(3);
}

static void do_stop ( void   )  [static]

Definition at line 852 of file pg_ctl.c.

References _, backup_file, do_wait, get_pgpid(), pg_usleep(), pid_file, print_msg(), progname, recovery_file, shutdown_mode, sig, SMART_MODE, strerror(), wait_seconds, and write_stderr.

Referenced by main().

{
    int         cnt;
    pgpid_t     pid;
    struct stat statbuf;

    pid = get_pgpid();

    if (pid == 0)               /* no pid file */
    {
        write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file);
        write_stderr(_("Is server running?\n"));
        exit(1);
    }
    else if (pid < 0)           /* standalone backend, not postmaster */
    {
        pid = -pid;
        write_stderr(_("%s: cannot stop server; "
                       "single-user server is running (PID: %ld)\n"),
                     progname, pid);
        exit(1);
    }

    if (kill((pid_t) pid, sig) != 0)
    {
        write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid,
                     strerror(errno));
        exit(1);
    }

    if (!do_wait)
    {
        print_msg(_("server shutting down\n"));
        return;
    }
    else
    {
        /*
         * If backup_label exists, an online backup is running. Warn the user
         * that smart shutdown will wait for it to finish. However, if
         * recovery.conf is also present, we're recovering from an online
         * backup instead of performing one.
         */
        if (shutdown_mode == SMART_MODE &&
            stat(backup_file, &statbuf) == 0 &&
            stat(recovery_file, &statbuf) != 0)
        {
            print_msg(_("WARNING: online backup mode is active\n"
                        "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
        }

        print_msg(_("waiting for server to shut down..."));

        for (cnt = 0; cnt < wait_seconds; cnt++)
        {
            if ((pid = get_pgpid()) != 0)
            {
                print_msg(".");
                pg_usleep(1000000);     /* 1 sec */
            }
            else
                break;
        }

        if (pid != 0)           /* pid file still exists */
        {
            print_msg(_(" failed\n"));

            write_stderr(_("%s: server does not shut down\n"), progname);
            if (shutdown_mode == SMART_MODE)
                write_stderr(_("HINT: The \"-m fast\" option immediately disconnects sessions rather than\n"
                          "waiting for session-initiated disconnection.\n"));
            exit(1);
        }
        print_msg(_(" done\n"));

        print_msg(_("server stopped\n"));
    }
}

static char* find_other_exec_or_die ( const char *  argv0,
const char *  target,
const char *  versionstr 
) [static]

Definition at line 707 of file pg_ctl.c.

References _, find_my_exec(), find_other_exec(), MAXPGPATH, pg_malloc(), progname, strlcpy(), and write_stderr.

Referenced by adjust_data_dir(), do_init(), and do_start().

{
    int         ret;
    char       *found_path;

    found_path = pg_malloc(MAXPGPATH);

    if ((ret = find_other_exec(argv0, target, versionstr, found_path)) < 0)
    {
        char        full_path[MAXPGPATH];

        if (find_my_exec(argv0, full_path) < 0)
            strlcpy(full_path, progname, sizeof(full_path));

        if (ret == -1)
            write_stderr(_("The program \"%s\" is needed by %s "
                           "but was not found in the\n"
                           "same directory as \"%s\".\n"
                           "Check your installation.\n"),
                         target, progname, full_path);
        else
            write_stderr(_("The program \"%s\" was found by \"%s\"\n"
                           "but was not the same version as %s.\n"
                           "Check your installation.\n"),
                         target, full_path, progname);
        exit(1);
    }

    return found_path;
}

static pgpid_t get_pgpid ( void   )  [static]

Definition at line 240 of file pg_ctl.c.

References _, NULL, pid_file, progname, strerror(), and write_stderr.

Referenced by do_promote(), do_reload(), do_restart(), do_start(), do_status(), and do_stop().

{
    FILE       *pidf;
    long        pid;

    pidf = fopen(pid_file, "r");
    if (pidf == NULL)
    {
        /* No pid file, not an error on startup */
        if (errno == ENOENT)
            return 0;
        else
        {
            write_stderr(_("%s: could not open PID file \"%s\": %s\n"),
                         progname, pid_file, strerror(errno));
            exit(1);
        }
    }
    if (fscanf(pidf, "%ld", &pid) != 1)
    {
        /* Is the file empty? */
        if (ftell(pidf) == 0 && feof(pidf))
            write_stderr(_("%s: the PID file \"%s\" is empty\n"),
                         progname, pid_file);
        else
            write_stderr(_("%s: invalid data in PID file \"%s\"\n"),
                         progname, pid_file);
        exit(1);
    }
    fclose(pidf);
    return (pgpid_t) pid;
}

int main ( int  argc,
char **  argv 
)

Definition at line 1967 of file pg_ctl.c.

References _, adjust_data_dir(), allow_core_files, argv0, backup_file, canonicalize_path(), ctl_command, do_advice(), do_help(), do_init(), do_kill(), do_promote(), do_reload(), do_restart(), do_start(), do_status(), do_stop(), do_wait, exec_path, get_progname(), getopt_long(), INIT_COMMAND, KILL_COMMAND, log_file, MAXPGPATH, NO_COMMAND, NULL, optarg, optind, pg_config, pg_data, pg_malloc(), pg_strdup(), PG_TEXTDOMAIN, pgdata_opt, pid_file, post_opts, postopts_file, progname, PROMOTE_COMMAND, putenv, recovery_file, REGISTER_COMMAND, register_password, register_servicename, register_username, RELOAD_COMMAND, RESTART_COMMAND, RUN_AS_SERVICE_COMMAND, S_IRWXG, S_IRWXO, set_mode(), set_pglocale_pgservice(), set_sig(), sig, silent_mode, snprintf(), START_COMMAND, start_time, STATUS_COMMAND, STOP_COMMAND, UNREGISTER_COMMAND, wait_seconds, wait_set, and write_stderr.

{
    static struct option long_options[] = {
        {"help", no_argument, NULL, '?'},
        {"version", no_argument, NULL, 'V'},
        {"log", required_argument, NULL, 'l'},
        {"mode", required_argument, NULL, 'm'},
        {"pgdata", required_argument, NULL, 'D'},
        {"silent", no_argument, NULL, 's'},
        {"timeout", required_argument, NULL, 't'},
        {"core-files", no_argument, NULL, 'c'},
        {NULL, 0, NULL, 0}
    };

    int         option_index;
    int         c;
    pgpid_t     killproc = 0;

#if defined(WIN32) || defined(__CYGWIN__)
    setvbuf(stderr, NULL, _IONBF, 0);
#endif

    progname = get_progname(argv[0]);
    set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_ctl"));
    start_time = time(NULL);

    /*
     * save argv[0] so do_start() can look for the postmaster if necessary. we
     * don't look for postmaster here because in many cases we won't need it.
     */
    argv0 = argv[0];

    umask(S_IRWXG | S_IRWXO);

    /* support --help and --version even if invoked as root */
    if (argc > 1)
    {
        if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0 ||
            strcmp(argv[1], "-?") == 0)
        {
            do_help();
            exit(0);
        }
        else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0)
        {
            puts("pg_ctl (PostgreSQL) " PG_VERSION);
            exit(0);
        }
    }

    /*
     * Disallow running as root, to forestall any possible security holes.
     */
#ifndef WIN32
    if (geteuid() == 0)
    {
        write_stderr(_("%s: cannot be run as root\n"
                       "Please log in (using, e.g., \"su\") as the "
                       "(unprivileged) user that will\n"
                       "own the server process.\n"),
                     progname);
        exit(1);
    }
#endif

    /*
     * 'Action' can be before or after args so loop over both. Some
     * getopt_long() implementations will reorder argv[] to place all flags
     * first (GNU?), but we don't rely on it. Our /port version doesn't do
     * that.
     */
    optind = 1;

    /* process command-line options */
    while (optind < argc)
    {
        while ((c = getopt_long(argc, argv, "cD:l:m:N:o:p:P:sS:t:U:wW", long_options, &option_index)) != -1)
        {
            switch (c)
            {
                case 'D':
                    {
                        char       *pgdata_D;
                        char       *env_var = pg_malloc(strlen(optarg) + 8);

                        pgdata_D = pg_strdup(optarg);
                        canonicalize_path(pgdata_D);
                        snprintf(env_var, strlen(optarg) + 8, "PGDATA=%s",
                                 pgdata_D);
                        putenv(env_var);

                        /*
                         * We could pass PGDATA just in an environment
                         * variable but we do -D too for clearer postmaster
                         * 'ps' display
                         */
                        pgdata_opt = pg_malloc(strlen(pgdata_D) + 7);
                        snprintf(pgdata_opt, strlen(pgdata_D) + 7,
                                 "-D \"%s\" ",
                                 pgdata_D);
                        break;
                    }
                case 'l':
                    log_file = pg_strdup(optarg);
                    break;
                case 'm':
                    set_mode(optarg);
                    break;
                case 'N':
                    register_servicename = pg_strdup(optarg);
                    break;
                case 'o':
                    post_opts = pg_strdup(optarg);
                    break;
                case 'p':
                    exec_path = pg_strdup(optarg);
                    break;
                case 'P':
                    register_password = pg_strdup(optarg);
                    break;
                case 's':
                    silent_mode = true;
                    break;
                case 'S':
#if defined(WIN32) || defined(__CYGWIN__)
                    set_starttype(optarg);
#else
                    write_stderr(_("%s: -S option not supported on this platform\n"),
                                 progname);
                    exit(1);
#endif
                    break;
                case 't':
                    wait_seconds = atoi(optarg);
                    break;
                case 'U':
                    if (strchr(optarg, '\\'))
                        register_username = pg_strdup(optarg);
                    else
                        /* Prepend .\ for local accounts */
                    {
                        register_username = pg_malloc(strlen(optarg) + 3);
                        strcpy(register_username, ".\\");
                        strcat(register_username, optarg);
                    }
                    break;
                case 'w':
                    do_wait = true;
                    wait_set = true;
                    break;
                case 'W':
                    do_wait = false;
                    wait_set = true;
                    break;
                case 'c':
                    allow_core_files = true;
                    break;
                default:
                    /* getopt_long already issued a suitable error message */
                    do_advice();
                    exit(1);
            }
        }

        /* Process an action */
        if (optind < argc)
        {
            if (ctl_command != NO_COMMAND)
            {
                write_stderr(_("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]);
                do_advice();
                exit(1);
            }

            if (strcmp(argv[optind], "init") == 0
                || strcmp(argv[optind], "initdb") == 0)
                ctl_command = INIT_COMMAND;
            else if (strcmp(argv[optind], "start") == 0)
                ctl_command = START_COMMAND;
            else if (strcmp(argv[optind], "stop") == 0)
                ctl_command = STOP_COMMAND;
            else if (strcmp(argv[optind], "restart") == 0)
                ctl_command = RESTART_COMMAND;
            else if (strcmp(argv[optind], "reload") == 0)
                ctl_command = RELOAD_COMMAND;
            else if (strcmp(argv[optind], "status") == 0)
                ctl_command = STATUS_COMMAND;
            else if (strcmp(argv[optind], "promote") == 0)
                ctl_command = PROMOTE_COMMAND;
            else if (strcmp(argv[optind], "kill") == 0)
            {
                if (argc - optind < 3)
                {
                    write_stderr(_("%s: missing arguments for kill mode\n"), progname);
                    do_advice();
                    exit(1);
                }
                ctl_command = KILL_COMMAND;
                set_sig(argv[++optind]);
                killproc = atol(argv[++optind]);
            }
#if defined(WIN32) || defined(__CYGWIN__)
            else if (strcmp(argv[optind], "register") == 0)
                ctl_command = REGISTER_COMMAND;
            else if (strcmp(argv[optind], "unregister") == 0)
                ctl_command = UNREGISTER_COMMAND;
            else if (strcmp(argv[optind], "runservice") == 0)
                ctl_command = RUN_AS_SERVICE_COMMAND;
#endif
            else
            {
                write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]);
                do_advice();
                exit(1);
            }
            optind++;
        }
    }

    if (ctl_command == NO_COMMAND)
    {
        write_stderr(_("%s: no operation specified\n"), progname);
        do_advice();
        exit(1);
    }

    /* Note we put any -D switch into the env var above */
    pg_config = getenv("PGDATA");
    if (pg_config)
    {
        pg_config = pg_strdup(pg_config);
        canonicalize_path(pg_config);
        pg_data = pg_strdup(pg_config);
    }

    /* -D might point at config-only directory; if so find the real PGDATA */
    adjust_data_dir();

    /* Complain if -D needed and not provided */
    if (pg_config == NULL &&
        ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND)
    {
        write_stderr(_("%s: no database directory specified and environment variable PGDATA unset\n"),
                     progname);
        do_advice();
        exit(1);
    }

    if (!wait_set)
    {
        switch (ctl_command)
        {
            case RESTART_COMMAND:
            case START_COMMAND:
                do_wait = false;
                break;
            case STOP_COMMAND:
                do_wait = true;
                break;
            default:
                break;
        }
    }

    if (ctl_command == RELOAD_COMMAND)
    {
        sig = SIGHUP;
        do_wait = false;
    }

    if (pg_data)
    {
        snprintf(postopts_file, MAXPGPATH, "%s/postmaster.opts", pg_data);
        snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
        snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
        snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);
    }

    switch (ctl_command)
    {
        case INIT_COMMAND:
            do_init();
            break;
        case STATUS_COMMAND:
            do_status();
            break;
        case START_COMMAND:
            do_start();
            break;
        case STOP_COMMAND:
            do_stop();
            break;
        case RESTART_COMMAND:
            do_restart();
            break;
        case RELOAD_COMMAND:
            do_reload();
            break;
        case PROMOTE_COMMAND:
            do_promote();
            break;
        case KILL_COMMAND:
            do_kill(killproc);
            break;
#if defined(WIN32) || defined(__CYGWIN__)
        case REGISTER_COMMAND:
            pgwin32_doRegister();
            break;
        case UNREGISTER_COMMAND:
            pgwin32_doUnregister();
            break;
        case RUN_AS_SERVICE_COMMAND:
            pgwin32_doRunAsService();
            break;
#endif
        default:
            break;
    }

    exit(0);
}

static bool postmaster_is_alive ( pid_t  pid  )  [static]

Definition at line 1141 of file pg_ctl.c.

Referenced by do_restart(), do_status(), and test_postmaster_connection().

{
    /*
     * Test to see if the process is still there.  Note that we do not
     * consider an EPERM failure to mean that the process is still there;
     * EPERM must mean that the given PID belongs to some other userid, and
     * considering the permissions on $PGDATA, that means it's not the
     * postmaster we are after.
     *
     * Don't believe that our own PID or parent shell's PID is the postmaster,
     * either.  (Windows hasn't got getppid(), though.)
     */
    if (pid == getpid())
        return false;
#ifndef WIN32
    if (pid == getppid())
        return false;
#endif
    if (kill(pid, 0) == 0)
        return true;
    return false;
}

static void print_msg ( const char *  msg  )  [static]

Definition at line 230 of file pg_ctl.c.

References silent_mode.

Referenced by do_promote(), do_reload(), do_restart(), do_start(), do_stop(), and test_postmaster_connection().

{
    if (!silent_mode)
    {
        fputs(msg, stdout);
        fflush(stdout);
    }
}

static void read_post_opts ( void   )  [static]

Definition at line 657 of file pg_ctl.c.

References _, ctl_command, exec_path, NULL, post_opts, postopts_file, progname, readfile(), RESTART_COMMAND, and write_stderr.

Referenced by do_start().

{
    if (post_opts == NULL)
    {
        post_opts = "";         /* default */
        if (ctl_command == RESTART_COMMAND)
        {
            char      **optlines;

            optlines = readfile(postopts_file);
            if (optlines == NULL)
            {
                write_stderr(_("%s: could not read file \"%s\"\n"), progname, postopts_file);
                exit(1);
            }
            else if (optlines[0] == NULL || optlines[1] != NULL)
            {
                write_stderr(_("%s: option file \"%s\" must have exactly one line\n"),
                             progname, postopts_file);
                exit(1);
            }
            else
            {
                int         len;
                char       *optline;
                char       *arg1;

                optline = optlines[0];
                /* trim off line endings */
                len = strcspn(optline, "\r\n");
                optline[len] = '\0';

                /*
                 * Are we at the first option, as defined by space and
                 * double-quote?
                 */
                if ((arg1 = strstr(optline, " \"")) != NULL)
                {
                    *arg1 = '\0';       /* terminate so we get only program
                                         * name */
                    post_opts = arg1 + 1;       /* point past whitespace */
                }
                if (exec_path == NULL)
                    exec_path = optline;
            }
        }
    }
}

static char ** readfile ( const char *  path  )  [static]

Definition at line 278 of file pg_ctl.c.

References close, free, i, PG_BINARY, pg_malloc(), and read.

Referenced by do_status(), read_post_opts(), and test_postmaster_connection().

{
    int         fd;
    int         nlines;
    char      **result;
    char       *buffer;
    char       *linebegin;
    int         i;
    int         n;
    int         len;
    struct stat statbuf;

    /*
     * Slurp the file into memory.
     *
     * The file can change concurrently, so we read the whole file into memory
     * with a single read() call. That's not guaranteed to get an atomic
     * snapshot, but in practice, for a small file, it's close enough for the
     * current use.
     */
    fd = open(path, O_RDONLY | PG_BINARY, 0);
    if (fd < 0)
        return NULL;
    if (fstat(fd, &statbuf) < 0)
    {
        close(fd);
        return NULL;
    }
    if (statbuf.st_size == 0)
    {
        /* empty file */
        close(fd);
        result = (char **) pg_malloc(sizeof(char *));
        *result = NULL;
        return result;
    }
    buffer = pg_malloc(statbuf.st_size + 1);

    len = read(fd, buffer, statbuf.st_size + 1);
    close(fd);
    if (len != statbuf.st_size)
    {
        /* oops, the file size changed between fstat and read */
        free(buffer);
        return NULL;
    }

    /*
     * Count newlines. We expect there to be a newline after each full line,
     * including one at the end of file. If there isn't a newline at the end,
     * any characters after the last newline will be ignored.
     */
    nlines = 0;
    for (i = 0; i < len; i++)
    {
        if (buffer[i] == '\n')
            nlines++;
    }

    /* set up the result buffer */
    result = (char **) pg_malloc((nlines + 1) * sizeof(char *));

    /* now split the buffer into lines */
    linebegin = buffer;
    n = 0;
    for (i = 0; i < len; i++)
    {
        if (buffer[i] == '\n')
        {
            int     slen = &buffer[i] - linebegin + 1;
            char   *linebuf = pg_malloc(slen + 1);
            memcpy(linebuf, linebegin, slen);
            linebuf[slen] = '\0';
            result[n++] = linebuf;
            linebegin = &buffer[i + 1];
        }
    }
    result[n] = NULL;

    free(buffer);

    return result;
}

static void set_mode ( char *  modeopt  )  [static]

Definition at line 1829 of file pg_ctl.c.

References _, do_advice(), progname, shutdown_mode, sig, and write_stderr.

Referenced by main().

{
    if (strcmp(modeopt, "s") == 0 || strcmp(modeopt, "smart") == 0)
    {
        shutdown_mode = SMART_MODE;
        sig = SIGTERM;
    }
    else if (strcmp(modeopt, "f") == 0 || strcmp(modeopt, "fast") == 0)
    {
        shutdown_mode = FAST_MODE;
        sig = SIGINT;
    }
    else if (strcmp(modeopt, "i") == 0 || strcmp(modeopt, "immediate") == 0)
    {
        shutdown_mode = IMMEDIATE_MODE;
        sig = SIGQUIT;
    }
    else
    {
        write_stderr(_("%s: unrecognized shutdown mode \"%s\"\n"), progname, modeopt);
        do_advice();
        exit(1);
    }
}

static void set_sig ( char *  signame  )  [static]

Definition at line 1857 of file pg_ctl.c.

References _, do_advice(), progname, sig, and write_stderr.

Referenced by main().

{
    if (strcmp(signame, "HUP") == 0)
        sig = SIGHUP;
    else if (strcmp(signame, "INT") == 0)
        sig = SIGINT;
    else if (strcmp(signame, "QUIT") == 0)
        sig = SIGQUIT;
    else if (strcmp(signame, "ABRT") == 0)
        sig = SIGABRT;
#if 0
    /* probably should NOT provide SIGKILL */
    else if (strcmp(signame, "KILL") == 0)
        sig = SIGKILL;
#endif
    else if (strcmp(signame, "TERM") == 0)
        sig = SIGTERM;
    else if (strcmp(signame, "USR1") == 0)
        sig = SIGUSR1;
    else if (strcmp(signame, "USR2") == 0)
        sig = SIGUSR2;
    else
    {
        write_stderr(_("%s: unrecognized signal name \"%s\"\n"), progname, signame);
        do_advice();
        exit(1);
    }
}

static int start_postmaster ( void   )  [static]

Definition at line 369 of file pg_ctl.c.

References DEVNULL, exec_path, log_file, MAXPGPATH, NULL, pgdata_opt, post_opts, snprintf(), system(), and SYSTEMQUOTE.

{
    char        cmd[MAXPGPATH];

#ifndef WIN32

    /*
     * Since there might be quotes to handle here, it is easier simply to pass
     * everything to a shell to process them.
     *
     * XXX it would be better to fork and exec so that we would know the child
     * postmaster's PID directly; then test_postmaster_connection could use
     * the PID without having to rely on reading it back from the pidfile.
     */
    if (log_file != NULL)
        snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1 &" SYSTEMQUOTE,
                 exec_path, pgdata_opt, post_opts,
                 DEVNULL, log_file);
    else
        snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1 &" SYSTEMQUOTE,
                 exec_path, pgdata_opt, post_opts, DEVNULL);

    return system(cmd);
#else                           /* WIN32 */

    /*
     * On win32 we don't use system(). So we don't need to use & (which would
     * be START /B on win32). However, we still call the shell (CMD.EXE) with
     * it to handle redirection etc.
     */
    PROCESS_INFORMATION pi;

    if (log_file != NULL)
        snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
                 exec_path, pgdata_opt, post_opts, DEVNULL, log_file);
    else
        snprintf(cmd, MAXPGPATH, "CMD /C " SYSTEMQUOTE "\"%s\" %s%s < \"%s\" 2>&1" SYSTEMQUOTE,
                 exec_path, pgdata_opt, post_opts, DEVNULL);

    if (!CreateRestrictedProcess(cmd, &pi, false))
        return GetLastError();
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
#endif   /* WIN32 */
}

static PGPing test_postmaster_connection ( bool  do_checkpoint  )  [static]

Definition at line 425 of file pg_ctl.c.

References _, connstr, i, LOCK_FILE_LINE_LISTEN_ADDR, LOCK_FILE_LINE_PID, LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR, LOCK_FILE_LINE_START_TIME, MAXPGPATH, NULL, pg_usleep(), pid_file, postmaster_is_alive(), PQping(), PQPING_NO_ATTEMPT, PQPING_OK, print_msg(), progname, readfile(), snprintf(), start_time, status(), strlcpy(), wait_seconds, and write_stderr.

Referenced by do_start().

{
    PGPing      ret = PQPING_NO_RESPONSE;
    bool        found_stale_pidfile = false;
    pgpid_t     pm_pid = 0;
    char        connstr[MAXPGPATH * 2 + 256];
    int         i;

    /* if requested wait time is zero, return "still starting up" code */
    if (wait_seconds <= 0)
        return PQPING_REJECT;

    connstr[0] = '\0';

    for (i = 0; i < wait_seconds; i++)
    {
        /* Do we need a connection string? */
        if (connstr[0] == '\0')
        {
            /*----------
             * The number of lines in postmaster.pid tells us several things:
             *
             * # of lines
             *      0   lock file created but status not written
             *      2   pre-9.1 server, shared memory not created
             *      3   pre-9.1 server, shared memory created
             *      5   9.1+ server, ports not opened
             *      6   9.1+ server, shared memory not created
             *      7   9.1+ server, shared memory created
             *
             * This code does not support pre-9.1 servers.  On Unix machines
             * we could consider extracting the port number from the shmem
             * key, but that (a) is not robust, and (b) doesn't help with
             * finding out the socket directory.  And it wouldn't work anyway
             * on Windows.
             *
             * If we see less than 6 lines in postmaster.pid, just keep
             * waiting.
             *----------
             */
            char      **optlines;

            /* Try to read the postmaster.pid file */
            if ((optlines = readfile(pid_file)) != NULL &&
                optlines[0] != NULL &&
                optlines[1] != NULL &&
                optlines[2] != NULL)
            {
                if (optlines[3] == NULL)
                {
                    /* File is exactly three lines, must be pre-9.1 */
                    write_stderr(_("\n%s: -w option is not supported when starting a pre-9.1 server\n"),
                                 progname);
                    return PQPING_NO_ATTEMPT;
                }
                else if (optlines[4] != NULL &&
                         optlines[5] != NULL)
                {
                    /* File is complete enough for us, parse it */
                    long        pmpid;
                    time_t      pmstart;

                    /*
                     * Make sanity checks.  If it's for a standalone backend
                     * (negative PID), or the recorded start time is before
                     * pg_ctl started, then either we are looking at the wrong
                     * data directory, or this is a pre-existing pidfile that
                     * hasn't (yet?) been overwritten by our child postmaster.
                     * Allow 2 seconds slop for possible cross-process clock
                     * skew.
                     */
                    pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
                    pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
                    if (pmpid <= 0 || pmstart < start_time - 2)
                    {
                        /*
                         * Set flag to report stale pidfile if it doesn't get
                         * overwritten before we give up waiting.
                         */
                        found_stale_pidfile = true;
                    }
                    else
                    {
                        /*
                         * OK, seems to be a valid pidfile from our child.
                         */
                        int         portnum;
                        char       *sockdir;
                        char       *hostaddr;
                        char        host_str[MAXPGPATH];

                        found_stale_pidfile = false;
                        pm_pid = (pgpid_t) pmpid;

                        /*
                         * Extract port number and host string to use. Prefer
                         * using Unix socket if available.
                         */
                        portnum = atoi(optlines[LOCK_FILE_LINE_PORT - 1]);
                        sockdir = optlines[LOCK_FILE_LINE_SOCKET_DIR - 1];
                        hostaddr = optlines[LOCK_FILE_LINE_LISTEN_ADDR - 1];

                        /*
                         * While unix_socket_directories can accept relative
                         * directories, libpq's host parameter must have a
                         * leading slash to indicate a socket directory.  So,
                         * ignore sockdir if it's relative, and try to use TCP
                         * instead.
                         */
                        if (sockdir[0] == '/')
                            strlcpy(host_str, sockdir, sizeof(host_str));
                        else
                            strlcpy(host_str, hostaddr, sizeof(host_str));

                        /* remove trailing newline */
                        if (strchr(host_str, '\n') != NULL)
                            *strchr(host_str, '\n') = '\0';

                        /* Fail if couldn't get either sockdir or host addr */
                        if (host_str[0] == '\0')
                        {
                            write_stderr(_("\n%s: -w option cannot use a relative socket directory specification\n"),
                                         progname);
                            return PQPING_NO_ATTEMPT;
                        }

                        /* If postmaster is listening on "*", use localhost */
                        if (strcmp(host_str, "*") == 0)
                            strcpy(host_str, "localhost");

                        /*
                         * We need to set connect_timeout otherwise on Windows
                         * the Service Control Manager (SCM) will probably
                         * timeout first.
                         */
                        snprintf(connstr, sizeof(connstr),
                        "dbname=postgres port=%d host='%s' connect_timeout=5",
                                 portnum, host_str);
                    }
                }
            }
        }

        /* If we have a connection string, ping the server */
        if (connstr[0] != '\0')
        {
            ret = PQping(connstr);
            if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT)
                break;
        }

        /*
         * The postmaster should create postmaster.pid very soon after being
         * started.  If it's not there after we've waited 5 or more seconds,
         * assume startup failed and give up waiting.  (Note this covers both
         * cases where the pidfile was never created, and where it was created
         * and then removed during postmaster exit.)  Also, if there *is* a
         * file there but it appears stale, issue a suitable warning and give
         * up waiting.
         */
        if (i >= 5)
        {
            struct stat statbuf;

            if (stat(pid_file, &statbuf) != 0)
                return PQPING_NO_RESPONSE;

            if (found_stale_pidfile)
            {
                write_stderr(_("\n%s: this data directory appears to be running a pre-existing postmaster\n"),
                             progname);
                return PQPING_NO_RESPONSE;
            }
        }

        /*
         * If we've been able to identify the child postmaster's PID, check
         * the process is still alive.  This covers cases where the postmaster
         * successfully created the pidfile but then crashed without removing
         * it.
         */
        if (pm_pid > 0 && !postmaster_is_alive((pid_t) pm_pid))
            return PQPING_NO_RESPONSE;

        /* No response, or startup still in process; wait */
#if defined(WIN32)
        if (do_checkpoint)
        {
            /*
             * Increment the wait hint by 6 secs (connection timeout + sleep)
             * We must do this to indicate to the SCM that our startup time is
             * changing, otherwise it'll usually send a stop signal after 20
             * seconds, despite incrementing the checkpoint counter.
             */
            status.dwWaitHint += 6000;
            status.dwCheckPoint++;
            SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
        }
        else
#endif
            print_msg(".");

        pg_usleep(1000000);     /* 1 sec */
    }

    /* return result of last call to PQping */
    return ret;
}

static void write_stderr ( const char *  fmt,
  ... 
) [static]

Definition at line 196 of file pg_ctl.c.

References vsnprintf().

{
    va_list     ap;

    va_start(ap, fmt);
#if !defined(WIN32) && !defined(__CYGWIN__)
    /* On Unix, we just fprintf to stderr */
    vfprintf(stderr, fmt, ap);
#else

    /*
     * On Win32, we print to stderr if running on a console, or write to
     * eventlog if running as a service
     */
    if (!isatty(fileno(stderr)))    /* Running as a service */
    {
        char        errbuf[2048];       /* Arbitrary size? */

        vsnprintf(errbuf, sizeof(errbuf), fmt, ap);

        write_eventlog(EVENTLOG_ERROR_TYPE, errbuf);
    }
    else
        /* Not running as service, write to stderr */
        vfprintf(stderr, fmt, ap);
#endif
    va_end(ap);
}


Variable Documentation

bool allow_core_files = false [static]

Definition at line 94 of file pg_ctl.c.

Referenced by do_start(), and main().

char* argv0 = NULL [static]

Definition at line 93 of file pg_ctl.c.

Referenced by adjust_data_dir(), do_init(), do_start(), and main().

char backup_file[MAXPGPATH] [static]

Definition at line 99 of file pg_ctl.c.

Referenced by do_restart(), do_stop(), and main().

CtlCommand ctl_command = NO_COMMAND [static]

Definition at line 82 of file pg_ctl.c.

Referenced by do_start(), main(), and read_post_opts().

bool do_wait = false [static]

Definition at line 76 of file pg_ctl.c.

Referenced by do_start(), do_stop(), and main().

char* exec_path = NULL [static]

Definition at line 89 of file pg_ctl.c.

Referenced by adjust_data_dir(), do_init(), do_start(), main(), read_post_opts(), setup(), and start_postmaster().

char* log_file = NULL [static]

Definition at line 88 of file pg_ctl.c.

Referenced by main(), and start_postmaster().

char* pg_config = NULL [static]

Definition at line 84 of file pg_ctl.c.

Referenced by adjust_data_dir(), and main().

char* pg_data = NULL [static]

Definition at line 83 of file pg_ctl.c.

Referenced by adjust_data_dir(), do_promote(), and main().

char* pgdata_opt = NULL [static]

Definition at line 85 of file pg_ctl.c.

Referenced by adjust_data_dir(), do_init(), do_start(), main(), and start_postmaster().

char pid_file[MAXPGPATH] [static]
char* post_opts = NULL [static]

Definition at line 86 of file pg_ctl.c.

Referenced by adjust_data_dir(), do_init(), main(), read_post_opts(), and start_postmaster().

char postopts_file[MAXPGPATH] [static]

Definition at line 97 of file pg_ctl.c.

Referenced by do_status(), main(), and read_post_opts().

const char* progname [static]

Definition at line 87 of file pg_ctl.c.

char promote_file[MAXPGPATH] [static]

Definition at line 101 of file pg_ctl.c.

Referenced by do_promote().

char recovery_file[MAXPGPATH] [static]

Definition at line 100 of file pg_ctl.c.

Referenced by do_promote(), do_restart(), do_stop(), and main().

char* register_password = NULL [static]

Definition at line 92 of file pg_ctl.c.

Referenced by main().

char* register_servicename = "PostgreSQL" [static]

Definition at line 90 of file pg_ctl.c.

Referenced by main().

char* register_username = NULL [static]

Definition at line 91 of file pg_ctl.c.

Referenced by main().

ShutdownMode shutdown_mode = SMART_MODE [static]

Definition at line 80 of file pg_ctl.c.

Referenced by do_restart(), do_stop(), and set_mode().

int sig = SIGTERM [static]
bool silent_mode = false [static]

Definition at line 79 of file pg_ctl.c.

Referenced by do_init(), main(), and print_msg().

time_t start_time [static]

Definition at line 95 of file pg_ctl.c.

Referenced by main(), test_postmaster_connection(), test_timing(), and WaitLatchOrSocket().

int wait_seconds = DEFAULT_WAIT [static]

Definition at line 78 of file pg_ctl.c.

Referenced by do_restart(), do_stop(), main(), and test_postmaster_connection().

bool wait_set = false [static]

Definition at line 77 of file pg_ctl.c.

Referenced by main().