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