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