Header And Logo

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

startup.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * startup.c
00004  *
00005  * The Startup process initialises the server and performs any recovery
00006  * actions that have been specified. Notice that there is no "main loop"
00007  * since the Startup process ends as soon as initialisation is complete.
00008  * (in standby mode, one can think of the replay loop as a main loop,
00009  * though.)
00010  *
00011  *
00012  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00013  *
00014  *
00015  * IDENTIFICATION
00016  *    src/backend/postmaster/startup.c
00017  *
00018  *-------------------------------------------------------------------------
00019  */
00020 #include "postgres.h"
00021 
00022 #include <signal.h>
00023 #include <unistd.h>
00024 
00025 #include "access/xlog.h"
00026 #include "libpq/pqsignal.h"
00027 #include "miscadmin.h"
00028 #include "postmaster/startup.h"
00029 #include "storage/ipc.h"
00030 #include "storage/latch.h"
00031 #include "storage/pmsignal.h"
00032 #include "storage/standby.h"
00033 #include "utils/guc.h"
00034 #include "utils/timeout.h"
00035 
00036 
00037 /*
00038  * Flags set by interrupt handlers for later service in the redo loop.
00039  */
00040 static volatile sig_atomic_t got_SIGHUP = false;
00041 static volatile sig_atomic_t shutdown_requested = false;
00042 static volatile sig_atomic_t promote_triggered = false;
00043 
00044 /*
00045  * Flag set when executing a restore command, to tell SIGTERM signal handler
00046  * that it's safe to just proc_exit.
00047  */
00048 static volatile sig_atomic_t in_restore_command = false;
00049 
00050 /* Signal handlers */
00051 static void startupproc_quickdie(SIGNAL_ARGS);
00052 static void StartupProcSigUsr1Handler(SIGNAL_ARGS);
00053 static void StartupProcTriggerHandler(SIGNAL_ARGS);
00054 static void StartupProcSigHupHandler(SIGNAL_ARGS);
00055 
00056 
00057 /* --------------------------------
00058  *      signal handler routines
00059  * --------------------------------
00060  */
00061 
00062 /*
00063  * startupproc_quickdie() occurs when signalled SIGQUIT by the postmaster.
00064  *
00065  * Some backend has bought the farm,
00066  * so we need to stop what we're doing and exit.
00067  */
00068 static void
00069 startupproc_quickdie(SIGNAL_ARGS)
00070 {
00071     PG_SETMASK(&BlockSig);
00072 
00073     /*
00074      * We DO NOT want to run proc_exit() callbacks -- we're here because
00075      * shared memory may be corrupted, so we don't want to try to clean up our
00076      * transaction.  Just nail the windows shut and get out of town.  Now that
00077      * there's an atexit callback to prevent third-party code from breaking
00078      * things by calling exit() directly, we have to reset the callbacks
00079      * explicitly to make this work as intended.
00080      */
00081     on_exit_reset();
00082 
00083     /*
00084      * Note we do exit(2) not exit(0).  This is to force the postmaster into a
00085      * system reset cycle if some idiot DBA sends a manual SIGQUIT to a random
00086      * backend.  This is necessary precisely because we don't clean up our
00087      * shared memory state.  (The "dead man switch" mechanism in pmsignal.c
00088      * should ensure the postmaster sees this as a crash, too, but no harm in
00089      * being doubly sure.)
00090      */
00091     exit(2);
00092 }
00093 
00094 
00095 /* SIGUSR1: let latch facility handle the signal */
00096 static void
00097 StartupProcSigUsr1Handler(SIGNAL_ARGS)
00098 {
00099     int         save_errno = errno;
00100 
00101     latch_sigusr1_handler();
00102 
00103     errno = save_errno;
00104 }
00105 
00106 /* SIGUSR2: set flag to finish recovery */
00107 static void
00108 StartupProcTriggerHandler(SIGNAL_ARGS)
00109 {
00110     int         save_errno = errno;
00111 
00112     promote_triggered = true;
00113     WakeupRecovery();
00114 
00115     errno = save_errno;
00116 }
00117 
00118 /* SIGHUP: set flag to re-read config file at next convenient time */
00119 static void
00120 StartupProcSigHupHandler(SIGNAL_ARGS)
00121 {
00122     int         save_errno = errno;
00123 
00124     got_SIGHUP = true;
00125     WakeupRecovery();
00126 
00127     errno = save_errno;
00128 }
00129 
00130 /* SIGTERM: set flag to abort redo and exit */
00131 static void
00132 StartupProcShutdownHandler(SIGNAL_ARGS)
00133 {
00134     int         save_errno = errno;
00135 
00136     if (in_restore_command)
00137         proc_exit(1);
00138     else
00139         shutdown_requested = true;
00140     WakeupRecovery();
00141 
00142     errno = save_errno;
00143 }
00144 
00145 /* Handle SIGHUP and SIGTERM signals of startup process */
00146 void
00147 HandleStartupProcInterrupts(void)
00148 {
00149     /*
00150      * Check if we were requested to re-read config file.
00151      */
00152     if (got_SIGHUP)
00153     {
00154         got_SIGHUP = false;
00155         ProcessConfigFile(PGC_SIGHUP);
00156     }
00157 
00158     /*
00159      * Check if we were requested to exit without finishing recovery.
00160      */
00161     if (shutdown_requested)
00162         proc_exit(1);
00163 
00164     /*
00165      * Emergency bailout if postmaster has died.  This is to avoid the
00166      * necessity for manual cleanup of all postmaster children.
00167      */
00168     if (IsUnderPostmaster && !PostmasterIsAlive())
00169         exit(1);
00170 }
00171 
00172 
00173 /* ----------------------------------
00174  *  Startup Process main entry point
00175  * ----------------------------------
00176  */
00177 void
00178 StartupProcessMain(void)
00179 {
00180     /*
00181      * If possible, make this process a group leader, so that the postmaster
00182      * can signal any child processes too.
00183      */
00184 #ifdef HAVE_SETSID
00185     if (setsid() < 0)
00186         elog(FATAL, "setsid() failed: %m");
00187 #endif
00188 
00189     /*
00190      * Properly accept or ignore signals the postmaster might send us.
00191      */
00192     pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
00193     pqsignal(SIGINT, SIG_IGN);  /* ignore query cancel */
00194     pqsignal(SIGTERM, StartupProcShutdownHandler);      /* request shutdown */
00195     pqsignal(SIGQUIT, startupproc_quickdie);    /* hard crash time */
00196     InitializeTimeouts();       /* establishes SIGALRM handler */
00197     pqsignal(SIGPIPE, SIG_IGN);
00198     pqsignal(SIGUSR1, StartupProcSigUsr1Handler);
00199     pqsignal(SIGUSR2, StartupProcTriggerHandler);
00200 
00201     /*
00202      * Reset some signals that are accepted by postmaster but not here
00203      */
00204     pqsignal(SIGCHLD, SIG_DFL);
00205     pqsignal(SIGTTIN, SIG_DFL);
00206     pqsignal(SIGTTOU, SIG_DFL);
00207     pqsignal(SIGCONT, SIG_DFL);
00208     pqsignal(SIGWINCH, SIG_DFL);
00209 
00210     /*
00211      * Register timeouts needed for standby mode
00212      */
00213     RegisterTimeout(STANDBY_DEADLOCK_TIMEOUT, StandbyDeadLockHandler);
00214     RegisterTimeout(STANDBY_TIMEOUT, StandbyTimeoutHandler);
00215 
00216     /*
00217      * Unblock signals (they were blocked when the postmaster forked us)
00218      */
00219     PG_SETMASK(&UnBlockSig);
00220 
00221     /*
00222      * Do what we came for.
00223      */
00224     StartupXLOG();
00225 
00226     /*
00227      * Exit normally. Exit code 0 tells postmaster that we completed recovery
00228      * successfully.
00229      */
00230     proc_exit(0);
00231 }
00232 
00233 void
00234 PreRestoreCommand(void)
00235 {
00236     /*
00237      * Set in_restore_command to tell the signal handler that we should exit
00238      * right away on SIGTERM. We know that we're at a safe point to do that.
00239      * Check if we had already received the signal, so that we don't miss a
00240      * shutdown request received just before this.
00241      */
00242     in_restore_command = true;
00243     if (shutdown_requested)
00244         proc_exit(1);
00245 }
00246 
00247 void
00248 PostRestoreCommand(void)
00249 {
00250     in_restore_command = false;
00251 }
00252 
00253 bool
00254 IsPromoteTriggered(void)
00255 {
00256     return promote_triggered;
00257 }
00258 
00259 void
00260 ResetPromoteTriggered(void)
00261 {
00262     promote_triggered = false;
00263 }