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