/src/postgres/src/backend/storage/ipc/ipc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * ipc.c |
4 | | * POSTGRES inter-process communication definitions. |
5 | | * |
6 | | * This file is misnamed, as it no longer has much of anything directly |
7 | | * to do with IPC. The functionality here is concerned with managing |
8 | | * exit-time cleanup for either a postmaster or a backend. |
9 | | * |
10 | | * |
11 | | * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group |
12 | | * Portions Copyright (c) 1994, Regents of the University of California |
13 | | * |
14 | | * |
15 | | * IDENTIFICATION |
16 | | * src/backend/storage/ipc/ipc.c |
17 | | * |
18 | | *------------------------------------------------------------------------- |
19 | | */ |
20 | | #include "postgres.h" |
21 | | |
22 | | #include <signal.h> |
23 | | #include <unistd.h> |
24 | | #include <sys/stat.h> |
25 | | |
26 | | #include "miscadmin.h" |
27 | | #ifdef PROFILE_PID_DIR |
28 | | #include "postmaster/autovacuum.h" |
29 | | #endif |
30 | | #include "storage/dsm.h" |
31 | | #include "storage/ipc.h" |
32 | | #include "tcop/tcopprot.h" |
33 | | |
34 | | |
35 | | /* |
36 | | * This flag is set during proc_exit() to change ereport()'s behavior, |
37 | | * so that an ereport() from an on_proc_exit routine cannot get us out |
38 | | * of the exit procedure. We do NOT want to go back to the idle loop... |
39 | | */ |
40 | | bool proc_exit_inprogress = false; |
41 | | |
42 | | /* |
43 | | * Set when shmem_exit() is in progress. |
44 | | */ |
45 | | bool shmem_exit_inprogress = false; |
46 | | |
47 | | /* |
48 | | * This flag tracks whether we've called atexit() in the current process |
49 | | * (or in the parent postmaster). |
50 | | */ |
51 | | static bool atexit_callback_setup = false; |
52 | | |
53 | | /* local functions */ |
54 | | static void proc_exit_prepare(int code); |
55 | | |
56 | | |
57 | | /* ---------------------------------------------------------------- |
58 | | * exit() handling stuff |
59 | | * |
60 | | * These functions are in generally the same spirit as atexit(), |
61 | | * but provide some additional features we need --- in particular, |
62 | | * we want to register callbacks to invoke when we are disconnecting |
63 | | * from a broken shared-memory context but not exiting the postmaster. |
64 | | * |
65 | | * Callback functions can take zero, one, or two args: the first passed |
66 | | * arg is the integer exitcode, the second is the Datum supplied when |
67 | | * the callback was registered. |
68 | | * ---------------------------------------------------------------- |
69 | | */ |
70 | | |
71 | 0 | #define MAX_ON_EXITS 20 |
72 | | |
73 | | struct ONEXIT |
74 | | { |
75 | | pg_on_exit_callback function; |
76 | | Datum arg; |
77 | | }; |
78 | | |
79 | | static struct ONEXIT on_proc_exit_list[MAX_ON_EXITS]; |
80 | | static struct ONEXIT on_shmem_exit_list[MAX_ON_EXITS]; |
81 | | static struct ONEXIT before_shmem_exit_list[MAX_ON_EXITS]; |
82 | | |
83 | | static int on_proc_exit_index, |
84 | | on_shmem_exit_index, |
85 | | before_shmem_exit_index; |
86 | | |
87 | | |
88 | | /* ---------------------------------------------------------------- |
89 | | * proc_exit |
90 | | * |
91 | | * this function calls all the callbacks registered |
92 | | * for it (to free resources) and then calls exit. |
93 | | * |
94 | | * This should be the only function to call exit(). |
95 | | * -cim 2/6/90 |
96 | | * |
97 | | * Unfortunately, we can't really guarantee that add-on code |
98 | | * obeys the rule of not calling exit() directly. So, while |
99 | | * this is the preferred way out of the system, we also register |
100 | | * an atexit callback that will make sure cleanup happens. |
101 | | * ---------------------------------------------------------------- |
102 | | */ |
103 | | void |
104 | | proc_exit(int code) |
105 | 0 | { |
106 | | /* not safe if forked by system(), etc. */ |
107 | 0 | if (MyProcPid != (int) getpid()) |
108 | 0 | elog(PANIC, "proc_exit() called in child process"); |
109 | | |
110 | | /* Clean up everything that must be cleaned up */ |
111 | 0 | proc_exit_prepare(code); |
112 | |
|
113 | | #ifdef PROFILE_PID_DIR |
114 | | { |
115 | | /* |
116 | | * If we are profiling ourself then gprof's mcleanup() is about to |
117 | | * write out a profile to ./gmon.out. Since mcleanup() always uses a |
118 | | * fixed file name, each backend will overwrite earlier profiles. To |
119 | | * fix that, we create a separate subdirectory for each backend |
120 | | * (./gprof/pid) and 'cd' to that subdirectory before we exit() - that |
121 | | * forces mcleanup() to write each profile into its own directory. We |
122 | | * end up with something like: $PGDATA/gprof/8829/gmon.out |
123 | | * $PGDATA/gprof/8845/gmon.out ... |
124 | | * |
125 | | * To avoid undesirable disk space bloat, autovacuum workers are |
126 | | * discriminated against: all their gmon.out files go into the same |
127 | | * subdirectory. Without this, an installation that is "just sitting |
128 | | * there" nonetheless eats megabytes of disk space every few seconds. |
129 | | * |
130 | | * Note that we do this here instead of in an on_proc_exit() callback |
131 | | * because we want to ensure that this code executes last - we don't |
132 | | * want to interfere with any other on_proc_exit() callback. For the |
133 | | * same reason, we do not include it in proc_exit_prepare ... so if |
134 | | * you are exiting in the "wrong way" you won't drop your profile in a |
135 | | * nice place. |
136 | | */ |
137 | | char gprofDirName[32]; |
138 | | |
139 | | if (AmAutoVacuumWorkerProcess()) |
140 | | snprintf(gprofDirName, 32, "gprof/avworker"); |
141 | | else |
142 | | snprintf(gprofDirName, 32, "gprof/%d", (int) getpid()); |
143 | | |
144 | | /* |
145 | | * Use mkdir() instead of MakePGDirectory() since we aren't making a |
146 | | * PG directory here. |
147 | | */ |
148 | | mkdir("gprof", S_IRWXU | S_IRWXG | S_IRWXO); |
149 | | mkdir(gprofDirName, S_IRWXU | S_IRWXG | S_IRWXO); |
150 | | chdir(gprofDirName); |
151 | | } |
152 | | #endif |
153 | |
|
154 | 0 | elog(DEBUG3, "exit(%d)", code); |
155 | | |
156 | 0 | exit(code); |
157 | 0 | } |
158 | | |
159 | | /* |
160 | | * Code shared between proc_exit and the atexit handler. Note that in |
161 | | * normal exit through proc_exit, this will actually be called twice ... |
162 | | * but the second call will have nothing to do. |
163 | | */ |
164 | | static void |
165 | | proc_exit_prepare(int code) |
166 | 0 | { |
167 | | /* |
168 | | * Once we set this flag, we are committed to exit. Any ereport() will |
169 | | * NOT send control back to the main loop, but right back here. |
170 | | */ |
171 | 0 | proc_exit_inprogress = true; |
172 | | |
173 | | /* |
174 | | * Forget any pending cancel or die requests; we're doing our best to |
175 | | * close up shop already. Note that the signal handlers will not set |
176 | | * these flags again, now that proc_exit_inprogress is set. |
177 | | */ |
178 | 0 | InterruptPending = false; |
179 | 0 | ProcDiePending = false; |
180 | 0 | QueryCancelPending = false; |
181 | 0 | InterruptHoldoffCount = 1; |
182 | 0 | CritSectionCount = 0; |
183 | | |
184 | | /* |
185 | | * Also clear the error context stack, to prevent error callbacks from |
186 | | * being invoked by any elog/ereport calls made during proc_exit. Whatever |
187 | | * context they might want to offer is probably not relevant, and in any |
188 | | * case they are likely to fail outright after we've done things like |
189 | | * aborting any open transaction. (In normal exit scenarios the context |
190 | | * stack should be empty anyway, but it might not be in the case of |
191 | | * elog(FATAL) for example.) |
192 | | */ |
193 | 0 | error_context_stack = NULL; |
194 | | /* For the same reason, reset debug_query_string before it's clobbered */ |
195 | 0 | debug_query_string = NULL; |
196 | | |
197 | | /* do our shared memory exits first */ |
198 | 0 | shmem_exit(code); |
199 | |
|
200 | 0 | elog(DEBUG3, "proc_exit(%d): %d callbacks to make", |
201 | 0 | code, on_proc_exit_index); |
202 | | |
203 | | /* |
204 | | * call all the registered callbacks. |
205 | | * |
206 | | * Note that since we decrement on_proc_exit_index each time, if a |
207 | | * callback calls ereport(ERROR) or ereport(FATAL) then it won't be |
208 | | * invoked again when control comes back here (nor will the |
209 | | * previously-completed callbacks). So, an infinite loop should not be |
210 | | * possible. |
211 | | */ |
212 | 0 | while (--on_proc_exit_index >= 0) |
213 | 0 | on_proc_exit_list[on_proc_exit_index].function(code, |
214 | 0 | on_proc_exit_list[on_proc_exit_index].arg); |
215 | |
|
216 | 0 | on_proc_exit_index = 0; |
217 | 0 | } |
218 | | |
219 | | /* ------------------ |
220 | | * Run all of the on_shmem_exit routines --- but don't actually exit. |
221 | | * This is used by the postmaster to re-initialize shared memory and |
222 | | * semaphores after a backend dies horribly. As with proc_exit(), we |
223 | | * remove each callback from the list before calling it, to avoid |
224 | | * infinite loop in case of error. |
225 | | * ------------------ |
226 | | */ |
227 | | void |
228 | | shmem_exit(int code) |
229 | 0 | { |
230 | 0 | shmem_exit_inprogress = true; |
231 | | |
232 | | /* |
233 | | * Call before_shmem_exit callbacks. |
234 | | * |
235 | | * These should be things that need most of the system to still be up and |
236 | | * working, such as cleanup of temp relations, which requires catalog |
237 | | * access; or things that need to be completed because later cleanup steps |
238 | | * depend on them, such as releasing lwlocks. |
239 | | */ |
240 | 0 | elog(DEBUG3, "shmem_exit(%d): %d before_shmem_exit callbacks to make", |
241 | 0 | code, before_shmem_exit_index); |
242 | 0 | while (--before_shmem_exit_index >= 0) |
243 | 0 | before_shmem_exit_list[before_shmem_exit_index].function(code, |
244 | 0 | before_shmem_exit_list[before_shmem_exit_index].arg); |
245 | 0 | before_shmem_exit_index = 0; |
246 | | |
247 | | /* |
248 | | * Call dynamic shared memory callbacks. |
249 | | * |
250 | | * These serve the same purpose as late callbacks, but for dynamic shared |
251 | | * memory segments rather than the main shared memory segment. |
252 | | * dsm_backend_shutdown() has the same kind of progressive logic we use |
253 | | * for the main shared memory segment; namely, it unregisters each |
254 | | * callback before invoking it, so that we don't get stuck in an infinite |
255 | | * loop if one of those callbacks itself throws an ERROR or FATAL. |
256 | | * |
257 | | * Note that explicitly calling this function here is quite different from |
258 | | * registering it as an on_shmem_exit callback for precisely this reason: |
259 | | * if one dynamic shared memory callback errors out, the remaining |
260 | | * callbacks will still be invoked. Thus, hard-coding this call puts it |
261 | | * equal footing with callbacks for the main shared memory segment. |
262 | | */ |
263 | 0 | dsm_backend_shutdown(); |
264 | | |
265 | | /* |
266 | | * Call on_shmem_exit callbacks. |
267 | | * |
268 | | * These are generally releasing low-level shared memory resources. In |
269 | | * some cases, this is a backstop against the possibility that the early |
270 | | * callbacks might themselves fail, leading to re-entry to this routine; |
271 | | * in other cases, it's cleanup that only happens at process exit. |
272 | | */ |
273 | 0 | elog(DEBUG3, "shmem_exit(%d): %d on_shmem_exit callbacks to make", |
274 | 0 | code, on_shmem_exit_index); |
275 | 0 | while (--on_shmem_exit_index >= 0) |
276 | 0 | on_shmem_exit_list[on_shmem_exit_index].function(code, |
277 | 0 | on_shmem_exit_list[on_shmem_exit_index].arg); |
278 | 0 | on_shmem_exit_index = 0; |
279 | |
|
280 | 0 | shmem_exit_inprogress = false; |
281 | 0 | } |
282 | | |
283 | | /* ---------------------------------------------------------------- |
284 | | * atexit_callback |
285 | | * |
286 | | * Backstop to ensure that direct calls of exit() don't mess us up. |
287 | | * |
288 | | * Somebody who was being really uncooperative could call _exit(), |
289 | | * but for that case we have a "dead man switch" that will make the |
290 | | * postmaster treat it as a crash --- see pmsignal.c. |
291 | | * ---------------------------------------------------------------- |
292 | | */ |
293 | | static void |
294 | | atexit_callback(void) |
295 | 0 | { |
296 | | /* Clean up everything that must be cleaned up */ |
297 | | /* ... too bad we don't know the real exit code ... */ |
298 | 0 | proc_exit_prepare(-1); |
299 | 0 | } |
300 | | |
301 | | /* ---------------------------------------------------------------- |
302 | | * on_proc_exit |
303 | | * |
304 | | * this function adds a callback function to the list of |
305 | | * functions invoked by proc_exit(). -cim 2/6/90 |
306 | | * ---------------------------------------------------------------- |
307 | | */ |
308 | | void |
309 | | on_proc_exit(pg_on_exit_callback function, Datum arg) |
310 | 0 | { |
311 | 0 | if (on_proc_exit_index >= MAX_ON_EXITS) |
312 | 0 | ereport(FATAL, |
313 | 0 | (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), |
314 | 0 | errmsg_internal("out of on_proc_exit slots"))); |
315 | | |
316 | 0 | on_proc_exit_list[on_proc_exit_index].function = function; |
317 | 0 | on_proc_exit_list[on_proc_exit_index].arg = arg; |
318 | |
|
319 | 0 | ++on_proc_exit_index; |
320 | |
|
321 | 0 | if (!atexit_callback_setup) |
322 | 0 | { |
323 | 0 | atexit(atexit_callback); |
324 | 0 | atexit_callback_setup = true; |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | | /* ---------------------------------------------------------------- |
329 | | * before_shmem_exit |
330 | | * |
331 | | * Register early callback to perform user-level cleanup, |
332 | | * e.g. transaction abort, before we begin shutting down |
333 | | * low-level subsystems. |
334 | | * ---------------------------------------------------------------- |
335 | | */ |
336 | | void |
337 | | before_shmem_exit(pg_on_exit_callback function, Datum arg) |
338 | 0 | { |
339 | 0 | if (before_shmem_exit_index >= MAX_ON_EXITS) |
340 | 0 | ereport(FATAL, |
341 | 0 | (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), |
342 | 0 | errmsg_internal("out of before_shmem_exit slots"))); |
343 | | |
344 | 0 | before_shmem_exit_list[before_shmem_exit_index].function = function; |
345 | 0 | before_shmem_exit_list[before_shmem_exit_index].arg = arg; |
346 | |
|
347 | 0 | ++before_shmem_exit_index; |
348 | |
|
349 | 0 | if (!atexit_callback_setup) |
350 | 0 | { |
351 | 0 | atexit(atexit_callback); |
352 | 0 | atexit_callback_setup = true; |
353 | 0 | } |
354 | 0 | } |
355 | | |
356 | | /* ---------------------------------------------------------------- |
357 | | * on_shmem_exit |
358 | | * |
359 | | * Register ordinary callback to perform low-level shutdown |
360 | | * (e.g. releasing our PGPROC); run after before_shmem_exit |
361 | | * callbacks and before on_proc_exit callbacks. |
362 | | * ---------------------------------------------------------------- |
363 | | */ |
364 | | void |
365 | | on_shmem_exit(pg_on_exit_callback function, Datum arg) |
366 | 0 | { |
367 | 0 | if (on_shmem_exit_index >= MAX_ON_EXITS) |
368 | 0 | ereport(FATAL, |
369 | 0 | (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), |
370 | 0 | errmsg_internal("out of on_shmem_exit slots"))); |
371 | | |
372 | 0 | on_shmem_exit_list[on_shmem_exit_index].function = function; |
373 | 0 | on_shmem_exit_list[on_shmem_exit_index].arg = arg; |
374 | |
|
375 | 0 | ++on_shmem_exit_index; |
376 | |
|
377 | 0 | if (!atexit_callback_setup) |
378 | 0 | { |
379 | 0 | atexit(atexit_callback); |
380 | 0 | atexit_callback_setup = true; |
381 | 0 | } |
382 | 0 | } |
383 | | |
384 | | /* ---------------------------------------------------------------- |
385 | | * cancel_before_shmem_exit |
386 | | * |
387 | | * this function removes a previously-registered before_shmem_exit |
388 | | * callback. We only look at the latest entry for removal, as we |
389 | | * expect callers to add and remove temporary before_shmem_exit |
390 | | * callbacks in strict LIFO order. |
391 | | * ---------------------------------------------------------------- |
392 | | */ |
393 | | void |
394 | | cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg) |
395 | 0 | { |
396 | 0 | if (before_shmem_exit_index > 0 && |
397 | 0 | before_shmem_exit_list[before_shmem_exit_index - 1].function |
398 | 0 | == function && |
399 | 0 | before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg) |
400 | 0 | --before_shmem_exit_index; |
401 | 0 | else |
402 | 0 | elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIxPTR ") is not the latest entry", |
403 | 0 | function, arg); |
404 | 0 | } |
405 | | |
406 | | /* ---------------------------------------------------------------- |
407 | | * on_exit_reset |
408 | | * |
409 | | * this function clears all on_proc_exit() and on_shmem_exit() |
410 | | * registered functions. This is used just after forking a backend, |
411 | | * so that the backend doesn't believe it should call the postmaster's |
412 | | * on-exit routines when it exits... |
413 | | * ---------------------------------------------------------------- |
414 | | */ |
415 | | void |
416 | | on_exit_reset(void) |
417 | 0 | { |
418 | 0 | before_shmem_exit_index = 0; |
419 | 0 | on_shmem_exit_index = 0; |
420 | 0 | on_proc_exit_index = 0; |
421 | 0 | reset_on_dsm_detach(); |
422 | 0 | } |
423 | | |
424 | | /* ---------------------------------------------------------------- |
425 | | * check_on_shmem_exit_lists_are_empty |
426 | | * |
427 | | * Debugging check that no shmem cleanup handlers have been registered |
428 | | * prematurely in the current process. |
429 | | * ---------------------------------------------------------------- |
430 | | */ |
431 | | void |
432 | | check_on_shmem_exit_lists_are_empty(void) |
433 | 0 | { |
434 | 0 | if (before_shmem_exit_index) |
435 | 0 | elog(FATAL, "before_shmem_exit has been called prematurely"); |
436 | 0 | if (on_shmem_exit_index) |
437 | 0 | elog(FATAL, "on_shmem_exit has been called prematurely"); |
438 | | /* Checking DSM detach state seems unnecessary given the above */ |
439 | 0 | } |