summaryrefslogtreecommitdiff
path: root/src/backend/postmaster/startup.c
diff options
context:
space:
mode:
authorSimon Riggs <simon@2ndQuadrant.com>2011-11-02 14:25:01 +0000
committerSimon Riggs <simon@2ndQuadrant.com>2011-11-02 14:25:01 +0000
commit9aceb6ab3c202a5bf00d5f00436bb6ad285fc0bf (patch)
treea4ec05fb44b3356827a4cb6fd7649126fb1614f7 /src/backend/postmaster/startup.c
parent86e33648992cfc104836ab1fbb6e654308beb4a5 (diff)
downloadpostgresql-9aceb6ab3c202a5bf00d5f00436bb6ad285fc0bf.tar.gz
Refactor xlog.c to create src/backend/postmaster/startup.c
Startup process now has its own dedicated file, just like all other special/background processes. Reduces role and size of xlog.c
Diffstat (limited to 'src/backend/postmaster/startup.c')
-rw-r--r--src/backend/postmaster/startup.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
new file mode 100644
index 0000000000..c4146845f2
--- /dev/null
+++ b/src/backend/postmaster/startup.c
@@ -0,0 +1,259 @@
+/*-------------------------------------------------------------------------
+ *
+ * startup.c
+ *
+ * The Startup process initialises the server and performs any recovery
+ * actions that have been specified. Notice that there is no "main loop"
+ * since the Startup process ends as soon as initialisation is complete.
+ *
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/postmaster/startup.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <signal.h>
+#include <unistd.h>
+
+#include "access/xlog.h"
+#include "libpq/pqsignal.h"
+#include "miscadmin.h"
+#include "postmaster/startup.h"
+#include "storage/ipc.h"
+#include "storage/latch.h"
+#include "storage/pmsignal.h"
+#include "storage/proc.h"
+#include "utils/guc.h"
+
+
+/*
+ * Flags set by interrupt handlers for later service in the redo loop.
+ */
+static volatile sig_atomic_t got_SIGHUP = false;
+static volatile sig_atomic_t shutdown_requested = false;
+static volatile sig_atomic_t promote_triggered = false;
+
+/*
+ * Flag set when executing a restore command, to tell SIGTERM signal handler
+ * that it's safe to just proc_exit.
+ */
+static volatile sig_atomic_t in_restore_command = false;
+
+/* Signal handlers */
+static void startupproc_quickdie(SIGNAL_ARGS);
+static void StartupProcSigUsr1Handler(SIGNAL_ARGS);
+static void StartupProcTriggerHandler(SIGNAL_ARGS);
+static void StartupProcSigHupHandler(SIGNAL_ARGS);
+
+
+/* --------------------------------
+ * signal handler routines
+ * --------------------------------
+ */
+
+/*
+ * startupproc_quickdie() occurs when signalled SIGQUIT by the postmaster.
+ *
+ * Some backend has bought the farm,
+ * so we need to stop what we're doing and exit.
+ */
+static void
+startupproc_quickdie(SIGNAL_ARGS)
+{
+ PG_SETMASK(&BlockSig);
+
+ /*
+ * We DO NOT want to run proc_exit() callbacks -- we're here because
+ * shared memory may be corrupted, so we don't want to try to clean up our
+ * transaction. Just nail the windows shut and get out of town. Now that
+ * there's an atexit callback to prevent third-party code from breaking
+ * things by calling exit() directly, we have to reset the callbacks
+ * explicitly to make this work as intended.
+ */
+ on_exit_reset();
+
+ /*
+ * Note we do exit(2) not exit(0). This is to force the postmaster into a
+ * system reset cycle if some idiot DBA sends a manual SIGQUIT to a random
+ * backend. This is necessary precisely because we don't clean up our
+ * shared memory state. (The "dead man switch" mechanism in pmsignal.c
+ * should ensure the postmaster sees this as a crash, too, but no harm in
+ * being doubly sure.)
+ */
+ exit(2);
+}
+
+
+/* SIGUSR1: let latch facility handle the signal */
+static void
+StartupProcSigUsr1Handler(SIGNAL_ARGS)
+{
+ int save_errno = errno;
+
+ latch_sigusr1_handler();
+
+ errno = save_errno;
+}
+
+/* SIGUSR2: set flag to finish recovery */
+static void
+StartupProcTriggerHandler(SIGNAL_ARGS)
+{
+ int save_errno = errno;
+
+ promote_triggered = true;
+ WakeupRecovery();
+
+ errno = save_errno;
+}
+
+/* SIGHUP: set flag to re-read config file at next convenient time */
+static void
+StartupProcSigHupHandler(SIGNAL_ARGS)
+{
+ int save_errno = errno;
+
+ got_SIGHUP = true;
+ WakeupRecovery();
+
+ errno = save_errno;
+}
+
+/* SIGTERM: set flag to abort redo and exit */
+static void
+StartupProcShutdownHandler(SIGNAL_ARGS)
+{
+ int save_errno = errno;
+
+ if (in_restore_command)
+ proc_exit(1);
+ else
+ shutdown_requested = true;
+ WakeupRecovery();
+
+ errno = save_errno;
+}
+
+/* Handle SIGHUP and SIGTERM signals of startup process */
+void
+HandleStartupProcInterrupts(void)
+{
+ /*
+ * Check if we were requested to re-read config file.
+ */
+ if (got_SIGHUP)
+ {
+ got_SIGHUP = false;
+ ProcessConfigFile(PGC_SIGHUP);
+ }
+
+ /*
+ * Check if we were requested to exit without finishing recovery.
+ */
+ if (shutdown_requested)
+ proc_exit(1);
+
+ /*
+ * Emergency bailout if postmaster has died. This is to avoid the
+ * necessity for manual cleanup of all postmaster children.
+ */
+ if (IsUnderPostmaster && !PostmasterIsAlive())
+ exit(1);
+}
+
+
+/* ----------------------------------
+ * Startup Process main entry point
+ * ----------------------------------
+ */
+void
+StartupProcessMain(void)
+{
+ /*
+ * If possible, make this process a group leader, so that the postmaster
+ * can signal any child processes too.
+ */
+#ifdef HAVE_SETSID
+ if (setsid() < 0)
+ elog(FATAL, "setsid() failed: %m");
+#endif
+
+ /*
+ * Properly accept or ignore signals the postmaster might send us.
+ *
+ * Note: ideally we'd not enable handle_standby_sig_alarm unless actually
+ * doing hot standby, but we don't know that yet. Rely on it to not do
+ * anything if it shouldn't.
+ */
+ pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
+ pqsignal(SIGINT, SIG_IGN); /* ignore query cancel */
+ pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */
+ pqsignal(SIGQUIT, startupproc_quickdie); /* hard crash time */
+ if (EnableHotStandby)
+ pqsignal(SIGALRM, handle_standby_sig_alarm); /* ignored unless
+ * InHotStandby */
+ else
+ 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
+ */
+ pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGTTIN, SIG_DFL);
+ pqsignal(SIGTTOU, SIG_DFL);
+ pqsignal(SIGCONT, SIG_DFL);
+ pqsignal(SIGWINCH, SIG_DFL);
+
+ /*
+ * Unblock signals (they were blocked when the postmaster forked us)
+ */
+ PG_SETMASK(&UnBlockSig);
+
+ StartupXLOG();
+
+ /*
+ * Exit normally. Exit code 0 tells postmaster that we completed recovery
+ * successfully.
+ */
+ proc_exit(0);
+}
+
+void
+PreRestoreCommand(void)
+{
+ /*
+ * Set in_restore_command to tell the signal handler that we should exit
+ * right away on SIGTERM. We know that we're at a safe point to do that.
+ * Check if we had already received the signal, so that we don't miss a
+ * shutdown request received just before this.
+ */
+ in_restore_command = true;
+ if (shutdown_requested)
+ proc_exit(1);
+}
+
+void
+PostRestoreCommand(void)
+{
+ in_restore_command = false;
+}
+
+bool
+IsPromoteTriggered(void)
+{
+ return promote_triggered;
+}
+
+void
+ResetPromoteTriggered(void)
+{
+ promote_triggered = false;
+}