1 /*-------------------------------------------------------------------------
2  *
3  * startup.c
4  *
5  * The Startup process initialises the server and performs any recovery
6  * actions that have been specified. Notice that there is no "main loop"
7  * since the Startup process ends as soon as initialisation is complete.
8  * (in standby mode, one can think of the replay loop as a main loop,
9  * though.)
10  *
11  *
12  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
13  *
14  *
15  * IDENTIFICATION
16  *	  src/backend/postmaster/startup.c
17  *
18  *-------------------------------------------------------------------------
19  */
20 #include "postgres.h"
21 
22 #include <signal.h>
23 #include <unistd.h>
24 
25 #include "access/xlog.h"
26 #include "libpq/pqsignal.h"
27 #include "miscadmin.h"
28 #include "postmaster/startup.h"
29 #include "storage/ipc.h"
30 #include "storage/latch.h"
31 #include "storage/pmsignal.h"
32 #include "storage/standby.h"
33 #include "utils/guc.h"
34 #include "utils/timeout.h"
35 
36 
37 /*
38  * Flags set by interrupt handlers for later service in the redo loop.
39  */
40 static volatile sig_atomic_t got_SIGHUP = false;
41 static volatile sig_atomic_t shutdown_requested = false;
42 static volatile sig_atomic_t promote_triggered = false;
43 
44 /*
45  * Flag set when executing a restore command, to tell SIGTERM signal handler
46  * that it's safe to just proc_exit.
47  */
48 static volatile sig_atomic_t in_restore_command = false;
49 
50 /* Signal handlers */
51 static void startupproc_quickdie(SIGNAL_ARGS);
52 static void StartupProcSigUsr1Handler(SIGNAL_ARGS);
53 static void StartupProcTriggerHandler(SIGNAL_ARGS);
54 static void StartupProcSigHupHandler(SIGNAL_ARGS);
55 
56 /* Callbacks */
57 static void StartupProcExit(int code, Datum arg);
58 
59 
60 /* --------------------------------
61  *		signal handler routines
62  * --------------------------------
63  */
64 
65 /*
66  * startupproc_quickdie() occurs when signalled SIGQUIT by the postmaster.
67  *
68  * Some backend has bought the farm,
69  * so we need to stop what we're doing and exit.
70  */
71 static void
startupproc_quickdie(SIGNAL_ARGS)72 startupproc_quickdie(SIGNAL_ARGS)
73 {
74 	/*
75 	 * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here
76 	 * because shared memory may be corrupted, so we don't want to try to
77 	 * clean up our transaction.  Just nail the windows shut and get out of
78 	 * town.  The callbacks wouldn't be safe to run from a signal handler,
79 	 * anyway.
80 	 *
81 	 * Note we do _exit(2) not _exit(0).  This is to force the postmaster into
82 	 * a system reset cycle if someone sends a manual SIGQUIT to a random
83 	 * backend.  This is necessary precisely because we don't clean up our
84 	 * shared memory state.  (The "dead man switch" mechanism in pmsignal.c
85 	 * should ensure the postmaster sees this as a crash, too, but no harm in
86 	 * being doubly sure.)
87 	 */
88 	_exit(2);
89 }
90 
91 
92 /* SIGUSR1: let latch facility handle the signal */
93 static void
StartupProcSigUsr1Handler(SIGNAL_ARGS)94 StartupProcSigUsr1Handler(SIGNAL_ARGS)
95 {
96 	int			save_errno = errno;
97 
98 	latch_sigusr1_handler();
99 
100 	errno = save_errno;
101 }
102 
103 /* SIGUSR2: set flag to finish recovery */
104 static void
StartupProcTriggerHandler(SIGNAL_ARGS)105 StartupProcTriggerHandler(SIGNAL_ARGS)
106 {
107 	int			save_errno = errno;
108 
109 	promote_triggered = true;
110 	WakeupRecovery();
111 
112 	errno = save_errno;
113 }
114 
115 /* SIGHUP: set flag to re-read config file at next convenient time */
116 static void
StartupProcSigHupHandler(SIGNAL_ARGS)117 StartupProcSigHupHandler(SIGNAL_ARGS)
118 {
119 	int			save_errno = errno;
120 
121 	got_SIGHUP = true;
122 	WakeupRecovery();
123 
124 	errno = save_errno;
125 }
126 
127 /* SIGTERM: set flag to abort redo and exit */
128 static void
StartupProcShutdownHandler(SIGNAL_ARGS)129 StartupProcShutdownHandler(SIGNAL_ARGS)
130 {
131 	int			save_errno = errno;
132 
133 	if (in_restore_command)
134 		proc_exit(1);
135 	else
136 		shutdown_requested = true;
137 	WakeupRecovery();
138 
139 	errno = save_errno;
140 }
141 
142 /* Handle SIGHUP and SIGTERM signals of startup process */
143 void
HandleStartupProcInterrupts(void)144 HandleStartupProcInterrupts(void)
145 {
146 	/*
147 	 * Check if we were requested to re-read config file.
148 	 */
149 	if (got_SIGHUP)
150 	{
151 		got_SIGHUP = false;
152 		ProcessConfigFile(PGC_SIGHUP);
153 	}
154 
155 	/*
156 	 * Check if we were requested to exit without finishing recovery.
157 	 */
158 	if (shutdown_requested)
159 		proc_exit(1);
160 
161 	/*
162 	 * Emergency bailout if postmaster has died.  This is to avoid the
163 	 * necessity for manual cleanup of all postmaster children.
164 	 */
165 	if (IsUnderPostmaster && !PostmasterIsAlive())
166 		exit(1);
167 }
168 
169 
170 /* --------------------------------
171  *		signal handler routines
172  * --------------------------------
173  */
174 static void
StartupProcExit(int code,Datum arg)175 StartupProcExit(int code, Datum arg)
176 {
177 	/* Shutdown the recovery environment */
178 	if (standbyState != STANDBY_DISABLED)
179 		ShutdownRecoveryTransactionEnvironment();
180 }
181 
182 
183 /* ----------------------------------
184  *	Startup Process main entry point
185  * ----------------------------------
186  */
187 void
StartupProcessMain(void)188 StartupProcessMain(void)
189 {
190 	/* Arrange to clean up at startup process exit */
191 	on_shmem_exit(StartupProcExit, 0);
192 
193 	/*
194 	 * Properly accept or ignore signals the postmaster might send us.
195 	 */
196 	pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
197 	pqsignal(SIGINT, SIG_IGN);	/* ignore query cancel */
198 	pqsignal(SIGTERM, StartupProcShutdownHandler);		/* request shutdown */
199 	pqsignal(SIGQUIT, startupproc_quickdie);	/* hard crash time */
200 	InitializeTimeouts();		/* establishes SIGALRM handler */
201 	pqsignal(SIGPIPE, SIG_IGN);
202 	pqsignal(SIGUSR1, StartupProcSigUsr1Handler);
203 	pqsignal(SIGUSR2, StartupProcTriggerHandler);
204 
205 	/*
206 	 * Reset some signals that are accepted by postmaster but not here
207 	 */
208 	pqsignal(SIGCHLD, SIG_DFL);
209 	pqsignal(SIGTTIN, SIG_DFL);
210 	pqsignal(SIGTTOU, SIG_DFL);
211 	pqsignal(SIGCONT, SIG_DFL);
212 	pqsignal(SIGWINCH, SIG_DFL);
213 
214 	/*
215 	 * Register timeouts needed for standby mode
216 	 */
217 	RegisterTimeout(STANDBY_DEADLOCK_TIMEOUT, StandbyDeadLockHandler);
218 	RegisterTimeout(STANDBY_TIMEOUT, StandbyTimeoutHandler);
219 	RegisterTimeout(STANDBY_LOCK_TIMEOUT, StandbyLockTimeoutHandler);
220 
221 	/*
222 	 * Unblock signals (they were blocked when the postmaster forked us)
223 	 */
224 	PG_SETMASK(&UnBlockSig);
225 
226 	/*
227 	 * Do what we came for.
228 	 */
229 	StartupXLOG();
230 
231 	/*
232 	 * Exit normally. Exit code 0 tells postmaster that we completed recovery
233 	 * successfully.
234 	 */
235 	proc_exit(0);
236 }
237 
238 void
PreRestoreCommand(void)239 PreRestoreCommand(void)
240 {
241 	/*
242 	 * Set in_restore_command to tell the signal handler that we should exit
243 	 * right away on SIGTERM. We know that we're at a safe point to do that.
244 	 * Check if we had already received the signal, so that we don't miss a
245 	 * shutdown request received just before this.
246 	 */
247 	in_restore_command = true;
248 	if (shutdown_requested)
249 		proc_exit(1);
250 }
251 
252 void
PostRestoreCommand(void)253 PostRestoreCommand(void)
254 {
255 	in_restore_command = false;
256 }
257 
258 bool
IsPromoteTriggered(void)259 IsPromoteTriggered(void)
260 {
261 	return promote_triggered;
262 }
263 
264 void
ResetPromoteTriggered(void)265 ResetPromoteTriggered(void)
266 {
267 	promote_triggered = false;
268 }
269