Age Owner Branch data TLA Line data Source code
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-2024, 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 : : #if defined(ENABLE_COVERAGE) && defined(HAVE___GCOV_DUMP)
27 : : #include <gcov.h>
28 : : #endif
29 : :
30 : : #include "miscadmin.h"
31 : : #ifdef PROFILE_PID_DIR
32 : : #include "postmaster/autovacuum.h"
33 : : #endif
34 : : #include "storage/dsm.h"
35 : : #include "storage/ipc.h"
36 : : #include "tcop/tcopprot.h"
37 : :
38 : :
39 : : /*
40 : : * This flag is set during proc_exit() to change ereport()'s behavior,
41 : : * so that an ereport() from an on_proc_exit routine cannot get us out
42 : : * of the exit procedure. We do NOT want to go back to the idle loop...
43 : : */
44 : : bool proc_exit_inprogress = false;
45 : :
46 : : /*
47 : : * Set when shmem_exit() is in progress.
48 : : */
49 : : bool shmem_exit_inprogress = false;
50 : :
51 : : /*
52 : : * Has exit() or _exit() been reached? We want to trigger code coverage
53 : : * emission during abnormal process exit, but the abnormal process exit could
54 : : * be triggered while already in a normal process exit(), corrupting code
55 : : * coverage information.
56 : : */
57 : : static bool system_exit_inprogress = false;
58 : :
59 : : /*
60 : : * This flag tracks whether we've called atexit() in the current process
61 : : * (or in the parent postmaster).
62 : : */
63 : : static bool atexit_callback_setup = false;
64 : :
65 : : /* local functions */
66 : : static void proc_exit_prepare(int code);
67 : :
68 : :
69 : : /* ----------------------------------------------------------------
70 : : * exit() handling stuff
71 : : *
72 : : * These functions are in generally the same spirit as atexit(),
73 : : * but provide some additional features we need --- in particular,
74 : : * we want to register callbacks to invoke when we are disconnecting
75 : : * from a broken shared-memory context but not exiting the postmaster.
76 : : *
77 : : * Callback functions can take zero, one, or two args: the first passed
78 : : * arg is the integer exitcode, the second is the Datum supplied when
79 : : * the callback was registered.
80 : : * ----------------------------------------------------------------
81 : : */
82 : :
83 : : #define MAX_ON_EXITS 20
84 : :
85 : : struct ONEXIT
86 : : {
87 : : pg_on_exit_callback function;
88 : : Datum arg;
89 : : };
90 : :
91 : : static struct ONEXIT on_proc_exit_list[MAX_ON_EXITS];
92 : : static struct ONEXIT on_shmem_exit_list[MAX_ON_EXITS];
93 : : static struct ONEXIT before_shmem_exit_list[MAX_ON_EXITS];
94 : :
95 : : static int on_proc_exit_index,
96 : : on_shmem_exit_index,
97 : : before_shmem_exit_index;
98 : :
99 : :
100 : : /* ----------------------------------------------------------------
101 : : * proc_exit
102 : : *
103 : : * this function calls all the callbacks registered
104 : : * for it (to free resources) and then calls exit.
105 : : *
106 : : * This should be the only function to call exit().
107 : : * -cim 2/6/90
108 : : *
109 : : * Unfortunately, we can't really guarantee that add-on code
110 : : * obeys the rule of not calling exit() directly. So, while
111 : : * this is the preferred way out of the system, we also register
112 : : * an atexit callback that will make sure cleanup happens.
113 : : * ----------------------------------------------------------------
114 : : */
115 : : void
9423 bruce@momjian.us 116 :CBC 19097 : proc_exit(int code)
117 : : {
118 : : /* not safe if forked by system(), etc. */
180 nathan@postgresql.or 119 [ - + ]: 19097 : if (MyProcPid != (int) getpid())
180 nathan@postgresql.or 120 [ # # ]:UBC 0 : elog(PANIC, "proc_exit() called in child process");
121 : :
122 : : /* Clean up everything that must be cleaned up */
5458 tgl@sss.pgh.pa.us 123 :CBC 19097 : proc_exit_prepare(code);
124 : :
125 : : #ifdef PROFILE_PID_DIR
126 : : {
127 : : /*
128 : : * If we are profiling ourself then gprof's mcleanup() is about to
129 : : * write out a profile to ./gmon.out. Since mcleanup() always uses a
130 : : * fixed file name, each backend will overwrite earlier profiles. To
131 : : * fix that, we create a separate subdirectory for each backend
132 : : * (./gprof/pid) and 'cd' to that subdirectory before we exit() - that
133 : : * forces mcleanup() to write each profile into its own directory. We
134 : : * end up with something like: $PGDATA/gprof/8829/gmon.out
135 : : * $PGDATA/gprof/8845/gmon.out ...
136 : : *
137 : : * To avoid undesirable disk space bloat, autovacuum workers are
138 : : * discriminated against: all their gmon.out files go into the same
139 : : * subdirectory. Without this, an installation that is "just sitting
140 : : * there" nonetheless eats megabytes of disk space every few seconds.
141 : : *
142 : : * Note that we do this here instead of in an on_proc_exit() callback
143 : : * because we want to ensure that this code executes last - we don't
144 : : * want to interfere with any other on_proc_exit() callback. For the
145 : : * same reason, we do not include it in proc_exit_prepare ... so if
146 : : * you are exiting in the "wrong way" you won't drop your profile in a
147 : : * nice place.
148 : : */
149 : : char gprofDirName[32];
150 : :
151 : : if (AmAutoVacuumWorkerProcess())
152 : : snprintf(gprofDirName, 32, "gprof/avworker");
153 : : else
154 : : snprintf(gprofDirName, 32, "gprof/%d", (int) getpid());
155 : :
156 : : /*
157 : : * Use mkdir() instead of MakePGDirectory() since we aren't making a
158 : : * PG directory here.
159 : : */
160 : : mkdir("gprof", S_IRWXU | S_IRWXG | S_IRWXO);
161 : : mkdir(gprofDirName, S_IRWXU | S_IRWXG | S_IRWXO);
162 : : chdir(gprofDirName);
163 : : }
164 : : #endif
165 : :
166 [ - + ]: 19095 : elog(DEBUG3, "exit(%d)", code);
167 : :
9716 bruce@momjian.us 168 : 19095 : exit(code);
169 : : }
170 : :
171 : : /*
172 : : * Code shared between proc_exit and the atexit handler. Note that in
173 : : * normal exit through proc_exit, this will actually be called twice ...
174 : : * but the second call will have nothing to do.
175 : : */
176 : : static void
5458 tgl@sss.pgh.pa.us 177 : 38163 : proc_exit_prepare(int code)
178 : : {
179 : : /*
180 : : * Once we set this flag, we are committed to exit. Any ereport() will
181 : : * NOT send control back to the main loop, but right back here.
182 : : */
183 : 38163 : proc_exit_inprogress = true;
184 : :
185 : : /*
186 : : * Forget any pending cancel or die requests; we're doing our best to
187 : : * close up shop already. Note that the signal handlers will not set
188 : : * these flags again, now that proc_exit_inprogress is set.
189 : : */
190 : 38163 : InterruptPending = false;
191 : 38163 : ProcDiePending = false;
192 : 38163 : QueryCancelPending = false;
193 : 38163 : InterruptHoldoffCount = 1;
194 : 38163 : CritSectionCount = 0;
195 : :
196 : : /*
197 : : * Also clear the error context stack, to prevent error callbacks from
198 : : * being invoked by any elog/ereport calls made during proc_exit. Whatever
199 : : * context they might want to offer is probably not relevant, and in any
200 : : * case they are likely to fail outright after we've done things like
201 : : * aborting any open transaction. (In normal exit scenarios the context
202 : : * stack should be empty anyway, but it might not be in the case of
203 : : * elog(FATAL) for example.)
204 : : */
5139 205 : 38163 : error_context_stack = NULL;
206 : : /* For the same reason, reset debug_query_string before it's clobbered */
207 : 38163 : debug_query_string = NULL;
208 : :
209 : : /* do our shared memory exits first */
5458 210 : 38163 : shmem_exit(code);
211 : :
5448 212 [ - + ]: 38161 : elog(DEBUG3, "proc_exit(%d): %d callbacks to make",
213 : : code, on_proc_exit_index);
214 : :
215 : : /*
216 : : * call all the registered callbacks.
217 : : *
218 : : * Note that since we decrement on_proc_exit_index each time, if a
219 : : * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
220 : : * invoked again when control comes back here (nor will the
221 : : * previously-completed callbacks). So, an infinite loop should not be
222 : : * possible.
223 : : */
5458 224 [ + + ]: 69508 : while (--on_proc_exit_index >= 0)
2411 peter_e@gmx.net 225 : 31347 : on_proc_exit_list[on_proc_exit_index].function(code,
226 : : on_proc_exit_list[on_proc_exit_index].arg);
227 : :
5458 tgl@sss.pgh.pa.us 228 : 38161 : on_proc_exit_index = 0;
229 : :
230 : : /*
231 : : * Postgres portion of process exit is done. Tell immediate_exit() to not
232 : : * trigger code coverage emission going forward.
233 : : */
0 andres@anarazel.de 234 : 38161 : system_exit_inprogress = true;
5458 tgl@sss.pgh.pa.us 235 : 38161 : }
236 : :
237 : : /* ------------------
238 : : * Run all of the on_shmem_exit routines --- but don't actually exit.
239 : : * This is used by the postmaster to re-initialize shared memory and
240 : : * semaphores after a backend dies horribly. As with proc_exit(), we
241 : : * remove each callback from the list before calling it, to avoid
242 : : * infinite loop in case of error.
243 : : * ------------------
244 : : */
245 : : void
9423 bruce@momjian.us 246 : 38168 : shmem_exit(int code)
247 : : {
2264 peter_e@gmx.net 248 : 38168 : shmem_exit_inprogress = true;
249 : :
250 : : /*
251 : : * Call before_shmem_exit callbacks.
252 : : *
253 : : * These should be things that need most of the system to still be up and
254 : : * working, such as cleanup of temp relations, which requires catalog
255 : : * access; or things that need to be completed because later cleanup steps
256 : : * depend on them, such as releasing lwlocks.
257 : : */
3770 rhaas@postgresql.org 258 [ - + ]: 38168 : elog(DEBUG3, "shmem_exit(%d): %d before_shmem_exit callbacks to make",
259 : : code, before_shmem_exit_index);
260 [ + + ]: 113544 : while (--before_shmem_exit_index >= 0)
2411 peter_e@gmx.net 261 : 75378 : before_shmem_exit_list[before_shmem_exit_index].function(code,
262 : : before_shmem_exit_list[before_shmem_exit_index].arg);
3770 rhaas@postgresql.org 263 : 38166 : before_shmem_exit_index = 0;
264 : :
265 : : /*
266 : : * Call dynamic shared memory callbacks.
267 : : *
268 : : * These serve the same purpose as late callbacks, but for dynamic shared
269 : : * memory segments rather than the main shared memory segment.
270 : : * dsm_backend_shutdown() has the same kind of progressive logic we use
271 : : * for the main shared memory segment; namely, it unregisters each
272 : : * callback before invoking it, so that we don't get stuck in an infinite
273 : : * loop if one of those callbacks itself throws an ERROR or FATAL.
274 : : *
275 : : * Note that explicitly calling this function here is quite different from
276 : : * registering it as an on_shmem_exit callback for precisely this reason:
277 : : * if one dynamic shared memory callback errors out, the remaining
278 : : * callbacks will still be invoked. Thus, hard-coding this call puts it
279 : : * equal footing with callbacks for the main shared memory segment.
280 : : */
281 : 38166 : dsm_backend_shutdown();
282 : :
283 : : /*
284 : : * Call on_shmem_exit callbacks.
285 : : *
286 : : * These are generally releasing low-level shared memory resources. In
287 : : * some cases, this is a backstop against the possibility that the early
288 : : * callbacks might themselves fail, leading to re-entry to this routine;
289 : : * in other cases, it's cleanup that only happens at process exit.
290 : : */
291 [ - + ]: 38166 : elog(DEBUG3, "shmem_exit(%d): %d on_shmem_exit callbacks to make",
292 : : code, on_shmem_exit_index);
8910 tgl@sss.pgh.pa.us 293 [ + + ]: 152018 : while (--on_shmem_exit_index >= 0)
2411 peter_e@gmx.net 294 : 113852 : on_shmem_exit_list[on_shmem_exit_index].function(code,
295 : : on_shmem_exit_list[on_shmem_exit_index].arg);
9423 bruce@momjian.us 296 : 38166 : on_shmem_exit_index = 0;
297 : :
2103 peter_e@gmx.net 298 : 38166 : shmem_exit_inprogress = false;
9423 bruce@momjian.us 299 : 38166 : }
300 : :
301 : : /* ----------------------------------------------------------------
302 : : * atexit_callback
303 : : *
304 : : * Backstop to ensure that direct calls of exit() don't mess us up.
305 : : *
306 : : * Somebody who was being really uncooperative could call _exit(),
307 : : * but for that case we have a "dead man switch" that will make the
308 : : * postmaster treat it as a crash --- see pmsignal.c.
309 : : * ----------------------------------------------------------------
310 : : */
311 : : static void
5458 tgl@sss.pgh.pa.us 312 : 19066 : atexit_callback(void)
313 : : {
314 : : /* Clean up everything that must be cleaned up */
315 : : /* ... too bad we don't know the real exit code ... */
316 : 19066 : proc_exit_prepare(-1);
317 : 19066 : }
318 : :
319 : : /* ----------------------------------------------------------------
320 : : * on_proc_exit
321 : : *
322 : : * this function adds a callback function to the list of
323 : : * functions invoked by proc_exit(). -cim 2/6/90
324 : : * ----------------------------------------------------------------
325 : : */
326 : : void
5842 327 : 32935 : on_proc_exit(pg_on_exit_callback function, Datum arg)
328 : : {
9423 bruce@momjian.us 329 [ - + ]: 32935 : if (on_proc_exit_index >= MAX_ON_EXITS)
7570 tgl@sss.pgh.pa.us 330 [ # # ]:UBC 0 : ereport(FATAL,
331 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
332 : : errmsg_internal("out of on_proc_exit slots")));
333 : :
9423 bruce@momjian.us 334 :CBC 32935 : on_proc_exit_list[on_proc_exit_index].function = function;
335 : 32935 : on_proc_exit_list[on_proc_exit_index].arg = arg;
336 : :
337 : 32935 : ++on_proc_exit_index;
338 : :
5458 tgl@sss.pgh.pa.us 339 [ + + ]: 32935 : if (!atexit_callback_setup)
340 : : {
341 : 899 : atexit(atexit_callback);
342 : 899 : atexit_callback_setup = true;
343 : : }
10141 scrappy@hub.org 344 : 32935 : }
345 : :
346 : : /* ----------------------------------------------------------------
347 : : * before_shmem_exit
348 : : *
349 : : * Register early callback to perform user-level cleanup,
350 : : * e.g. transaction abort, before we begin shutting down
351 : : * low-level subsystems.
352 : : * ----------------------------------------------------------------
353 : : */
354 : : void
3770 rhaas@postgresql.org 355 : 83980 : before_shmem_exit(pg_on_exit_callback function, Datum arg)
356 : : {
357 [ - + ]: 83980 : if (before_shmem_exit_index >= MAX_ON_EXITS)
3770 rhaas@postgresql.org 358 [ # # ]:UBC 0 : ereport(FATAL,
359 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
360 : : errmsg_internal("out of before_shmem_exit slots")));
361 : :
3770 rhaas@postgresql.org 362 :CBC 83980 : before_shmem_exit_list[before_shmem_exit_index].function = function;
363 : 83980 : before_shmem_exit_list[before_shmem_exit_index].arg = arg;
364 : :
365 : 83980 : ++before_shmem_exit_index;
366 : :
367 [ - + ]: 83980 : if (!atexit_callback_setup)
368 : : {
3770 rhaas@postgresql.org 369 :UBC 0 : atexit(atexit_callback);
370 : 0 : atexit_callback_setup = true;
371 : : }
3770 rhaas@postgresql.org 372 :CBC 83980 : }
373 : :
374 : : /* ----------------------------------------------------------------
375 : : * on_shmem_exit
376 : : *
377 : : * Register ordinary callback to perform low-level shutdown
378 : : * (e.g. releasing our PGPROC); run after before_shmem_exit
379 : : * callbacks and before on_proc_exit callbacks.
380 : : * ----------------------------------------------------------------
381 : : */
382 : : void
5842 tgl@sss.pgh.pa.us 383 : 122255 : on_shmem_exit(pg_on_exit_callback function, Datum arg)
384 : : {
9423 bruce@momjian.us 385 [ - + ]: 122255 : if (on_shmem_exit_index >= MAX_ON_EXITS)
7570 tgl@sss.pgh.pa.us 386 [ # # ]:UBC 0 : ereport(FATAL,
387 : : (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
388 : : errmsg_internal("out of on_shmem_exit slots")));
389 : :
9423 bruce@momjian.us 390 :CBC 122255 : on_shmem_exit_list[on_shmem_exit_index].function = function;
391 : 122255 : on_shmem_exit_list[on_shmem_exit_index].arg = arg;
392 : :
393 : 122255 : ++on_shmem_exit_index;
394 : :
5458 tgl@sss.pgh.pa.us 395 [ - + ]: 122255 : if (!atexit_callback_setup)
396 : : {
5458 tgl@sss.pgh.pa.us 397 :UBC 0 : atexit(atexit_callback);
398 : 0 : atexit_callback_setup = true;
399 : : }
10141 scrappy@hub.org 400 :CBC 122255 : }
401 : :
402 : : /* ----------------------------------------------------------------
403 : : * cancel_before_shmem_exit
404 : : *
405 : : * this function removes a previously-registered before_shmem_exit
406 : : * callback. We only look at the latest entry for removal, as we
407 : : * expect callers to add and remove temporary before_shmem_exit
408 : : * callbacks in strict LIFO order.
409 : : * ----------------------------------------------------------------
410 : : */
411 : : void
3770 rhaas@postgresql.org 412 : 1866 : cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg)
413 : : {
414 [ + - ]: 1866 : if (before_shmem_exit_index > 0 &&
415 [ + - ]: 1866 : before_shmem_exit_list[before_shmem_exit_index - 1].function
3631 bruce@momjian.us 416 : 1866 : == function &&
3770 rhaas@postgresql.org 417 [ + - ]: 1866 : before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg)
418 : 1866 : --before_shmem_exit_index;
419 : : else
1314 tgl@sss.pgh.pa.us 420 [ # # ]:UBC 0 : elog(ERROR, "before_shmem_exit callback (%p,0x%llx) is not the latest entry",
421 : : function, (long long) arg);
5842 tgl@sss.pgh.pa.us 422 :CBC 1866 : }
423 : :
424 : : /* ----------------------------------------------------------------
425 : : * on_exit_reset
426 : : *
427 : : * this function clears all on_proc_exit() and on_shmem_exit()
428 : : * registered functions. This is used just after forking a backend,
429 : : * so that the backend doesn't believe it should call the postmaster's
430 : : * on-exit routines when it exits...
431 : : * ----------------------------------------------------------------
432 : : */
433 : : void
9423 bruce@momjian.us 434 : 19697 : on_exit_reset(void)
435 : : {
3770 rhaas@postgresql.org 436 : 19697 : before_shmem_exit_index = 0;
9423 bruce@momjian.us 437 : 19697 : on_shmem_exit_index = 0;
438 : 19697 : on_proc_exit_index = 0;
3688 rhaas@postgresql.org 439 : 19697 : reset_on_dsm_detach();
9452 bruce@momjian.us 440 : 19697 : }
441 : :
442 : : /* ----------------------------------------------------------------
443 : : * check_on_shmem_exit_lists_are_empty
444 : : *
445 : : * Debugging check that no shmem cleanup handlers have been registered
446 : : * prematurely in the current process.
447 : : * ----------------------------------------------------------------
448 : : */
449 : : void
1311 tgl@sss.pgh.pa.us 450 : 11313 : check_on_shmem_exit_lists_are_empty(void)
451 : : {
452 [ - + ]: 11313 : if (before_shmem_exit_index)
1311 tgl@sss.pgh.pa.us 453 [ # # ]:UBC 0 : elog(FATAL, "before_shmem_exit has been called prematurely");
1311 tgl@sss.pgh.pa.us 454 [ - + ]:CBC 11313 : if (on_shmem_exit_index)
1311 tgl@sss.pgh.pa.us 455 [ # # ]:UBC 0 : elog(FATAL, "on_shmem_exit has been called prematurely");
456 : : /* Checking DSM detach state seems unnecessary given the above */
1311 tgl@sss.pgh.pa.us 457 :CBC 11313 : }
458 : :
459 : : /*
460 : : * Wrapper around _exit() that deals with code coverage etc.
461 : : *
462 : : * _exit() is used when running atexit handlers etc would risk a
463 : : * self-deadlock or such, e.g. because we're exiting from a signal
464 : : * handler. Therefore it is not correct to run any code that is not async
465 : : * signal safe.
466 : : *
467 : : * Unfortunately, gcc's code coverage implementation dumps its coverage
468 : : * information using atexit. As we shut down using _exit() in various
469 : : * situations, this leads to incomplete code coverage information being
470 : : * emitted.
471 : : */
472 : : void
0 andres@anarazel.de 473 : 1530 : immediate_exit(int code)
474 : : {
475 : : /*
476 : : * NOTE: In a production build, everything here needs to be async signal
477 : : * safe!
478 : : */
479 [ + - ]: 1530 : if (!system_exit_inprogress)
480 : : {
481 : 1530 : system_exit_inprogress = true;
482 : :
483 : :
484 : : #if defined(ENABLE_COVERAGE) && defined(HAVE___GCOV_DUMP)
485 : : /*
486 : : * Only dump coverage information if this process isn't already in the
487 : : * process of exiting. Otherwise gcov's atexit handler could already
488 : : * be inside __gcov_dump(), leading to corrupted coverage files (often
489 : : * triggering "negative hit counts" warnings in lcov).
490 : : *
491 : : * This does *not* completely foreclose corruption due to abnormal
492 : : * process termination, as __gcov_dump() can be interrupted by a
493 : : * signal, leading to incompletely written files. It makes the window
494 : : * for that a lot narrower though.
495 : : *
496 : : * We could possibly increase changs of success by ignoring
497 : : * immedate_exit() while __gcov_dump() is in progress, but that seems
498 : : * too gnarly.
499 : : */
500 : 1530 : __gcov_dump();
501 : : #endif /* defined(ENABLE_COVERAGE) && defined(HAVE___GCOV_DUMP) */
502 : : }
503 : :
0 andres@anarazel.de 504 :UBC 0 : _exit(code);
505 : : }
|