*** a/doc/src/sgml/ref/pg_ctl-ref.sgml
--- b/doc/src/sgml/ref/pg_ctl-ref.sgml
***************
*** 77,82 **** PostgreSQL documentation
--- 77,89 ----
  
    <cmdsynopsis>
     <command>pg_ctl</command>
+    <arg choice="plain">failover</arg>
+    <arg>-s</arg>
+    <arg>-D <replaceable>datadir</replaceable></arg>
+   </cmdsynopsis>
+ 
+   <cmdsynopsis>
+    <command>pg_ctl</command>
     <arg choice="plain">reload</arg>
     <arg>-s</arg>
     <arg>-D <replaceable>datadir</replaceable></arg>
***************
*** 184,189 **** PostgreSQL documentation
--- 191,201 ----
    </para>
  
    <para>
+    In <option>failover</option> mode, the standby server that is
+    running in the specified data directory is promoted to the primary.
+   </para>
+ 
+   <para>
     <option>reload</option> mode simply sends the
     <command>postgres</command> process a <systemitem>SIGHUP</>
     signal, causing it to reread its configuration files
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 64,69 ****
--- 64,70 ----
  #define BACKUP_LABEL_OLD		"backup_label.old"
  #define RECOVERY_COMMAND_FILE	"recovery.conf"
  #define RECOVERY_COMMAND_DONE	"recovery.done"
+ #define FAILOVER_SIGNAL_FILE	"failover"
  
  
  /* User-settable parameters */
***************
*** 546,551 **** typedef struct xl_parameter_change
--- 547,553 ----
   */
  static volatile sig_atomic_t got_SIGHUP = false;
  static volatile sig_atomic_t shutdown_requested = false;
+ static volatile sig_atomic_t standby_triggered = false;
  
  /*
   * Flag set when executing a restore command, to tell SIGTERM signal handler
***************
*** 9196,9201 **** StartupProcSigUsr1Handler(SIGNAL_ARGS)
--- 9198,9211 ----
  	latch_sigusr1_handler();
  }
  
+ /* SIGUSR2: set flag to finish recovery */
+ static void
+ StartupProcTriggerHandler(SIGNAL_ARGS)
+ {
+ 	standby_triggered = true;
+ 	WakeupRecovery();
+ }
+ 
  /* SIGHUP: set flag to re-read config file at next convenient time */
  static void
  StartupProcSigHupHandler(SIGNAL_ARGS)
***************
*** 9273,9279 **** StartupProcessMain(void)
  		pqsignal(SIGALRM, SIG_IGN);
  	pqsignal(SIGPIPE, SIG_IGN);
  	pqsignal(SIGUSR1, StartupProcSigUsr1Handler);
! 	pqsignal(SIGUSR2, SIG_IGN);
  
  	/*
  	 * Reset some signals that are accepted by postmaster but not here
--- 9283,9289 ----
  		pqsignal(SIGALRM, SIG_IGN);
  	pqsignal(SIGPIPE, SIG_IGN);
  	pqsignal(SIGUSR1, StartupProcSigUsr1Handler);
! 	pqsignal(SIGUSR2, StartupProcTriggerHandler);
  
  	/*
  	 * Reset some signals that are accepted by postmaster but not here
***************
*** 9719,9733 **** emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
  }
  
  /*
!  * Check to see if the trigger file exists. If it does, request postmaster
!  * to shut down walreceiver, wait for it to exit, remove the trigger
!  * file, and return true.
   */
  static bool
  CheckForStandbyTrigger(void)
  {
  	struct stat stat_buf;
  
  	if (TriggerFile == NULL)
  		return false;
  
--- 9729,9753 ----
  }
  
  /*
!  * Check to see if the user-specified trigger file exists and
!  * if a failover has been requested by pg_ctl. If either does,
!  * request postmaster to shut down walreceiver, wait for it to exit,
!  * and return true.
   */
  static bool
  CheckForStandbyTrigger(void)
  {
  	struct stat stat_buf;
  
+ 	if (standby_triggered)
+ 	{
+ 		ereport(LOG,
+ 				(errmsg("failover requested")));
+ 		ShutdownWalRcv();
+ 		standby_triggered = false;
+ 		return true;
+ 	}
+ 
  	if (TriggerFile == NULL)
  		return false;
  
***************
*** 9743,9748 **** CheckForStandbyTrigger(void)
--- 9763,9789 ----
  }
  
  /*
+  * Check to see if a failover has been requested by pg_ctl. Should be
+  * called by postmaster after receiving SIGUSR1.
+  */
+ bool
+ CheckFailoverSignal(void)
+ {
+ 	struct stat stat_buf;
+ 
+ 	if (stat(FAILOVER_SIGNAL_FILE, &stat_buf) == 0)
+ 	{
+ 		/*
+ 		 * Since we are in a signal handler, it's not safe
+ 		 * to elog. We silently ignore the error of unlink.
+ 		 */
+ 		unlink(FAILOVER_SIGNAL_FILE);
+ 		return true;
+ 	}
+ 	return false;
+ }
+ 
+ /*
   * Wake up startup process to replay newly arrived WAL, or to notice that
   * failover has been requested.
   */
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
***************
*** 4271,4276 **** sigusr1_handler(SIGNAL_ARGS)
--- 4271,4284 ----
  		WalReceiverPID = StartWalReceiver();
  	}
  
+ 	if (CheckFailoverSignal() && StartupPID != 0 &&
+ 		(pmState == PM_STARTUP || pmState == PM_RECOVERY ||
+ 		 pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY))
+ 	{
+ 		/* Tell startup process to finish recovery */
+ 		signal_child(StartupPID, SIGUSR2);
+ 	}
+ 
  	PG_SETMASK(&UnBlockSig);
  
  	errno = save_errno;
*** a/src/bin/pg_ctl/pg_ctl.c
--- b/src/bin/pg_ctl/pg_ctl.c
***************
*** 63,68 **** typedef enum
--- 63,69 ----
  	START_COMMAND,
  	STOP_COMMAND,
  	RESTART_COMMAND,
+ 	FAILOVER_COMMAND,
  	RELOAD_COMMAND,
  	STATUS_COMMAND,
  	KILL_COMMAND,
***************
*** 107,112 **** static void do_init(void);
--- 108,114 ----
  static void do_start(void);
  static void do_stop(void);
  static void do_restart(void);
+ static void do_failover(void);
  static void do_reload(void);
  static void do_status(void);
  static void do_kill(pgpid_t pid);
***************
*** 146,151 **** static char postopts_file[MAXPGPATH];
--- 148,154 ----
  static char pid_file[MAXPGPATH];
  static char backup_file[MAXPGPATH];
  static char recovery_file[MAXPGPATH];
+ static char failover_file[MAXPGPATH];
  
  #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
  static void unlimit_core_size(void);
***************
*** 871,877 **** do_stop(void)
  
  
  /*
!  *	restart/reload routines
   */
  
  static void
--- 874,880 ----
  
  
  /*
!  *	restart/failover/reload routines
   */
  
  static void
***************
*** 964,969 **** do_restart(void)
--- 967,1029 ----
  	do_start();
  }
  
+ static void
+ do_failover(void)
+ {
+ 	FILE	   *fofile;
+ 	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 request failover; "
+ 					   "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 request failover; "
+ 					   "server is not in standby mode\n"),
+ 					 progname);
+ 		exit(1);
+ 	}
+ 
+ 	if ((fofile = fopen(failover_file, "w")) == NULL)
+ 	{
+ 		write_stderr(_("%s: could not create failover signal file \"%s\": %s\n"),
+ 					 progname, failover_file, strerror(errno));
+ 		exit(1);
+ 	}
+ 	if (fclose(fofile))
+ 	{
+ 		write_stderr(_("%s: could not write failover signal file \"%s\": %s\n"),
+ 					 progname, failover_file, strerror(errno));
+ 		exit(1);
+ 	}
+ 
+ 	sig = SIGUSR1;
+ 	if (kill((pid_t) pid, sig) != 0)
+ 	{
+ 		write_stderr(_("%s: could not send failover signal (PID: %ld): %s\n"),
+ 					 progname, pid, strerror(errno));
+ 		exit(1);
+ 	}
+ 
+ 	print_msg(_("failover requested\n"));
+ }
+ 
  
  static void
  do_reload(void)
***************
*** 1616,1632 **** do_advice(void)
  static void
  do_help(void)
  {
! 	printf(_("%s is a utility to start, stop, restart, reload configuration files,\n"
  			 "report the status of a PostgreSQL server, or signal a PostgreSQL process.\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 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);
--- 1676,1693 ----
  static void
  do_help(void)
  {
! 	printf(_("%s is a utility to start, stop, restart, failover, reload configuration files,\n"
  			 "report the status of a PostgreSQL server, or signal a PostgreSQL process.\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 failover [-D DATADIR] [-s]\n"), progname);
! 	printf(_("  %s reload   [-D DATADIR] [-s]\n"), progname);
! 	printf(_("  %s status   [-D DATADIR]\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);
***************
*** 1949,1954 **** main(int argc, char **argv)
--- 2010,2017 ----
  				ctl_command = STOP_COMMAND;
  			else if (strcmp(argv[optind], "restart") == 0)
  				ctl_command = RESTART_COMMAND;
+ 			else if (strcmp(argv[optind], "failover") == 0)
+ 				ctl_command = FAILOVER_COMMAND;
  			else if (strcmp(argv[optind], "reload") == 0)
  				ctl_command = RELOAD_COMMAND;
  			else if (strcmp(argv[optind], "status") == 0)
***************
*** 2035,2040 **** main(int argc, char **argv)
--- 2098,2104 ----
  		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);
+ 		snprintf(failover_file, MAXPGPATH, "%s/failover", pg_data);
  	}
  
  	switch (ctl_command)
***************
*** 2054,2059 **** main(int argc, char **argv)
--- 2118,2126 ----
  		case RESTART_COMMAND:
  			do_restart();
  			break;
+ 		case FAILOVER_COMMAND:
+ 			do_failover();
+ 			break;
  		case RELOAD_COMMAND:
  			do_reload();
  			break;
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 310,315 **** extern TimeLineID GetRecoveryTargetTLI(void);
--- 310,316 ----
  
  extern void HandleStartupProcInterrupts(void);
  extern void StartupProcessMain(void);
+ extern bool CheckFailoverSignal(void);
  extern void WakeupRecovery(void);
  
  extern XLogRecPtr do_pg_start_backup(const char *backupidstr, bool fast);
