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