LCOV - differential code coverage report
Current view: top level - src/backend/storage/ipc - ipc.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 88.2 % 85 75 10 75
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 10 10 10
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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-2023, 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                 : #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 CBC       14589 : proc_exit(int code)
     105                 : {
     106                 :     /* Clean up everything that must be cleaned up */
     107           14589 :     proc_exit_prepare(code);
     108                 : 
     109                 : #ifdef PROFILE_PID_DIR
     110                 :     {
     111                 :         /*
     112                 :          * If we are profiling ourself then gprof's mcleanup() is about to
     113                 :          * write out a profile to ./gmon.out.  Since mcleanup() always uses a
     114                 :          * fixed file name, each backend will overwrite earlier profiles. To
     115                 :          * fix that, we create a separate subdirectory for each backend
     116                 :          * (./gprof/pid) and 'cd' to that subdirectory before we exit() - that
     117                 :          * forces mcleanup() to write each profile into its own directory.  We
     118                 :          * end up with something like: $PGDATA/gprof/8829/gmon.out
     119                 :          * $PGDATA/gprof/8845/gmon.out ...
     120                 :          *
     121                 :          * To avoid undesirable disk space bloat, autovacuum workers are
     122                 :          * discriminated against: all their gmon.out files go into the same
     123                 :          * subdirectory.  Without this, an installation that is "just sitting
     124                 :          * there" nonetheless eats megabytes of disk space every few seconds.
     125                 :          *
     126                 :          * Note that we do this here instead of in an on_proc_exit() callback
     127                 :          * because we want to ensure that this code executes last - we don't
     128                 :          * want to interfere with any other on_proc_exit() callback.  For the
     129                 :          * same reason, we do not include it in proc_exit_prepare ... so if
     130                 :          * you are exiting in the "wrong way" you won't drop your profile in a
     131                 :          * nice place.
     132                 :          */
     133                 :         char        gprofDirName[32];
     134                 : 
     135                 :         if (IsAutoVacuumWorkerProcess())
     136                 :             snprintf(gprofDirName, 32, "gprof/avworker");
     137                 :         else
     138                 :             snprintf(gprofDirName, 32, "gprof/%d", (int) getpid());
     139                 : 
     140                 :         /*
     141                 :          * Use mkdir() instead of MakePGDirectory() since we aren't making a
     142                 :          * PG directory here.
     143                 :          */
     144                 :         mkdir("gprof", S_IRWXU | S_IRWXG | S_IRWXO);
     145                 :         mkdir(gprofDirName, S_IRWXU | S_IRWXG | S_IRWXO);
     146                 :         chdir(gprofDirName);
     147                 :     }
     148                 : #endif
     149                 : 
     150           14589 :     elog(DEBUG3, "exit(%d)", code);
     151                 : 
     152           14589 :     exit(code);
     153                 : }
     154                 : 
     155                 : /*
     156                 :  * Code shared between proc_exit and the atexit handler.  Note that in
     157                 :  * normal exit through proc_exit, this will actually be called twice ...
     158                 :  * but the second call will have nothing to do.
     159                 :  */
     160                 : static void
     161           29149 : proc_exit_prepare(int code)
     162                 : {
     163                 :     /*
     164                 :      * Once we set this flag, we are committed to exit.  Any ereport() will
     165                 :      * NOT send control back to the main loop, but right back here.
     166                 :      */
     167           29149 :     proc_exit_inprogress = true;
     168                 : 
     169                 :     /*
     170                 :      * Forget any pending cancel or die requests; we're doing our best to
     171                 :      * close up shop already.  Note that the signal handlers will not set
     172                 :      * these flags again, now that proc_exit_inprogress is set.
     173                 :      */
     174           29149 :     InterruptPending = false;
     175           29149 :     ProcDiePending = false;
     176           29149 :     QueryCancelPending = false;
     177           29149 :     InterruptHoldoffCount = 1;
     178           29149 :     CritSectionCount = 0;
     179                 : 
     180                 :     /*
     181                 :      * Also clear the error context stack, to prevent error callbacks from
     182                 :      * being invoked by any elog/ereport calls made during proc_exit. Whatever
     183                 :      * context they might want to offer is probably not relevant, and in any
     184                 :      * case they are likely to fail outright after we've done things like
     185                 :      * aborting any open transaction.  (In normal exit scenarios the context
     186                 :      * stack should be empty anyway, but it might not be in the case of
     187                 :      * elog(FATAL) for example.)
     188                 :      */
     189           29149 :     error_context_stack = NULL;
     190                 :     /* For the same reason, reset debug_query_string before it's clobbered */
     191           29149 :     debug_query_string = NULL;
     192                 : 
     193                 :     /* do our shared memory exits first */
     194           29149 :     shmem_exit(code);
     195                 : 
     196           29149 :     elog(DEBUG3, "proc_exit(%d): %d callbacks to make",
     197                 :          code, on_proc_exit_index);
     198                 : 
     199                 :     /*
     200                 :      * call all the registered callbacks.
     201                 :      *
     202                 :      * Note that since we decrement on_proc_exit_index each time, if a
     203                 :      * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
     204                 :      * invoked again when control comes back here (nor will the
     205                 :      * previously-completed callbacks).  So, an infinite loop should not be
     206                 :      * possible.
     207                 :      */
     208           53952 :     while (--on_proc_exit_index >= 0)
     209           24803 :         on_proc_exit_list[on_proc_exit_index].function(code,
     210                 :                                                        on_proc_exit_list[on_proc_exit_index].arg);
     211                 : 
     212           29149 :     on_proc_exit_index = 0;
     213           29149 : }
     214                 : 
     215                 : /* ------------------
     216                 :  * Run all of the on_shmem_exit routines --- but don't actually exit.
     217                 :  * This is used by the postmaster to re-initialize shared memory and
     218                 :  * semaphores after a backend dies horribly.  As with proc_exit(), we
     219                 :  * remove each callback from the list before calling it, to avoid
     220                 :  * infinite loop in case of error.
     221                 :  * ------------------
     222                 :  */
     223                 : void
     224           29153 : shmem_exit(int code)
     225                 : {
     226           29153 :     shmem_exit_inprogress = true;
     227                 : 
     228                 :     /*
     229                 :      * Call before_shmem_exit callbacks.
     230                 :      *
     231                 :      * These should be things that need most of the system to still be up and
     232                 :      * working, such as cleanup of temp relations, which requires catalog
     233                 :      * access; or things that need to be completed because later cleanup steps
     234                 :      * depend on them, such as releasing lwlocks.
     235                 :      */
     236           29153 :     elog(DEBUG3, "shmem_exit(%d): %d before_shmem_exit callbacks to make",
     237                 :          code, before_shmem_exit_index);
     238           86281 :     while (--before_shmem_exit_index >= 0)
     239           57128 :         before_shmem_exit_list[before_shmem_exit_index].function(code,
     240                 :                                                                  before_shmem_exit_list[before_shmem_exit_index].arg);
     241           29153 :     before_shmem_exit_index = 0;
     242                 : 
     243                 :     /*
     244                 :      * Call dynamic shared memory callbacks.
     245                 :      *
     246                 :      * These serve the same purpose as late callbacks, but for dynamic shared
     247                 :      * memory segments rather than the main shared memory segment.
     248                 :      * dsm_backend_shutdown() has the same kind of progressive logic we use
     249                 :      * for the main shared memory segment; namely, it unregisters each
     250                 :      * callback before invoking it, so that we don't get stuck in an infinite
     251                 :      * loop if one of those callbacks itself throws an ERROR or FATAL.
     252                 :      *
     253                 :      * Note that explicitly calling this function here is quite different from
     254                 :      * registering it as an on_shmem_exit callback for precisely this reason:
     255                 :      * if one dynamic shared memory callback errors out, the remaining
     256                 :      * callbacks will still be invoked.  Thus, hard-coding this call puts it
     257                 :      * equal footing with callbacks for the main shared memory segment.
     258                 :      */
     259           29153 :     dsm_backend_shutdown();
     260                 : 
     261                 :     /*
     262                 :      * Call on_shmem_exit callbacks.
     263                 :      *
     264                 :      * These are generally releasing low-level shared memory resources.  In
     265                 :      * some cases, this is a backstop against the possibility that the early
     266                 :      * callbacks might themselves fail, leading to re-entry to this routine;
     267                 :      * in other cases, it's cleanup that only happens at process exit.
     268                 :      */
     269           29153 :     elog(DEBUG3, "shmem_exit(%d): %d on_shmem_exit callbacks to make",
     270                 :          code, on_shmem_exit_index);
     271          118809 :     while (--on_shmem_exit_index >= 0)
     272           89656 :         on_shmem_exit_list[on_shmem_exit_index].function(code,
     273                 :                                                          on_shmem_exit_list[on_shmem_exit_index].arg);
     274           29153 :     on_shmem_exit_index = 0;
     275                 : 
     276           29153 :     shmem_exit_inprogress = false;
     277           29153 : }
     278                 : 
     279                 : /* ----------------------------------------------------------------
     280                 :  *      atexit_callback
     281                 :  *
     282                 :  *      Backstop to ensure that direct calls of exit() don't mess us up.
     283                 :  *
     284                 :  * Somebody who was being really uncooperative could call _exit(),
     285                 :  * but for that case we have a "dead man switch" that will make the
     286                 :  * postmaster treat it as a crash --- see pmsignal.c.
     287                 :  * ----------------------------------------------------------------
     288                 :  */
     289                 : static void
     290           14560 : atexit_callback(void)
     291                 : {
     292                 :     /* Clean up everything that must be cleaned up */
     293                 :     /* ... too bad we don't know the real exit code ... */
     294           14560 :     proc_exit_prepare(-1);
     295           14560 : }
     296                 : 
     297                 : /* ----------------------------------------------------------------
     298                 :  *      on_proc_exit
     299                 :  *
     300                 :  *      this function adds a callback function to the list of
     301                 :  *      functions invoked by proc_exit().   -cim 2/6/90
     302                 :  * ----------------------------------------------------------------
     303                 :  */
     304                 : void
     305           24803 : on_proc_exit(pg_on_exit_callback function, Datum arg)
     306                 : {
     307           24803 :     if (on_proc_exit_index >= MAX_ON_EXITS)
     308 UBC           0 :         ereport(FATAL,
     309                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     310                 :                  errmsg_internal("out of on_proc_exit slots")));
     311                 : 
     312 CBC       24803 :     on_proc_exit_list[on_proc_exit_index].function = function;
     313           24803 :     on_proc_exit_list[on_proc_exit_index].arg = arg;
     314                 : 
     315           24803 :     ++on_proc_exit_index;
     316                 : 
     317           24803 :     if (!atexit_callback_setup)
     318                 :     {
     319            1828 :         atexit(atexit_callback);
     320            1828 :         atexit_callback_setup = true;
     321                 :     }
     322           24803 : }
     323                 : 
     324                 : /* ----------------------------------------------------------------
     325                 :  *      before_shmem_exit
     326                 :  *
     327                 :  *      Register early callback to perform user-level cleanup,
     328                 :  *      e.g. transaction abort, before we begin shutting down
     329                 :  *      low-level subsystems.
     330                 :  * ----------------------------------------------------------------
     331                 :  */
     332                 : void
     333           62199 : before_shmem_exit(pg_on_exit_callback function, Datum arg)
     334                 : {
     335           62199 :     if (before_shmem_exit_index >= MAX_ON_EXITS)
     336 UBC           0 :         ereport(FATAL,
     337                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     338                 :                  errmsg_internal("out of before_shmem_exit slots")));
     339                 : 
     340 CBC       62199 :     before_shmem_exit_list[before_shmem_exit_index].function = function;
     341           62199 :     before_shmem_exit_list[before_shmem_exit_index].arg = arg;
     342                 : 
     343           62199 :     ++before_shmem_exit_index;
     344                 : 
     345           62199 :     if (!atexit_callback_setup)
     346                 :     {
     347 UBC           0 :         atexit(atexit_callback);
     348               0 :         atexit_callback_setup = true;
     349                 :     }
     350 CBC       62199 : }
     351                 : 
     352                 : /* ----------------------------------------------------------------
     353                 :  *      on_shmem_exit
     354                 :  *
     355                 :  *      Register ordinary callback to perform low-level shutdown
     356                 :  *      (e.g. releasing our PGPROC); run after before_shmem_exit
     357                 :  *      callbacks and before on_proc_exit callbacks.
     358                 :  * ----------------------------------------------------------------
     359                 :  */
     360                 : void
     361           89656 : on_shmem_exit(pg_on_exit_callback function, Datum arg)
     362                 : {
     363           89656 :     if (on_shmem_exit_index >= MAX_ON_EXITS)
     364 UBC           0 :         ereport(FATAL,
     365                 :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     366                 :                  errmsg_internal("out of on_shmem_exit slots")));
     367                 : 
     368 CBC       89656 :     on_shmem_exit_list[on_shmem_exit_index].function = function;
     369           89656 :     on_shmem_exit_list[on_shmem_exit_index].arg = arg;
     370                 : 
     371           89656 :     ++on_shmem_exit_index;
     372                 : 
     373           89656 :     if (!atexit_callback_setup)
     374                 :     {
     375 UBC           0 :         atexit(atexit_callback);
     376               0 :         atexit_callback_setup = true;
     377                 :     }
     378 CBC       89656 : }
     379                 : 
     380                 : /* ----------------------------------------------------------------
     381                 :  *      cancel_before_shmem_exit
     382                 :  *
     383                 :  *      this function removes a previously-registered before_shmem_exit
     384                 :  *      callback.  We only look at the latest entry for removal, as we
     385                 :  *      expect callers to add and remove temporary before_shmem_exit
     386                 :  *      callbacks in strict LIFO order.
     387                 :  * ----------------------------------------------------------------
     388                 :  */
     389                 : void
     390            5071 : cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg)
     391                 : {
     392            5071 :     if (before_shmem_exit_index > 0 &&
     393            5071 :         before_shmem_exit_list[before_shmem_exit_index - 1].function
     394            5071 :         == function &&
     395            5071 :         before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg)
     396            5071 :         --before_shmem_exit_index;
     397                 :     else
     398 UBC           0 :         elog(ERROR, "before_shmem_exit callback (%p,0x%llx) is not the latest entry",
     399                 :              function, (long long) arg);
     400 CBC        5071 : }
     401                 : 
     402                 : /* ----------------------------------------------------------------
     403                 :  *      on_exit_reset
     404                 :  *
     405                 :  *      this function clears all on_proc_exit() and on_shmem_exit()
     406                 :  *      registered functions.  This is used just after forking a backend,
     407                 :  *      so that the backend doesn't believe it should call the postmaster's
     408                 :  *      on-exit routines when it exits...
     409                 :  * ----------------------------------------------------------------
     410                 :  */
     411                 : void
     412           12732 : on_exit_reset(void)
     413                 : {
     414           12732 :     before_shmem_exit_index = 0;
     415           12732 :     on_shmem_exit_index = 0;
     416           12732 :     on_proc_exit_index = 0;
     417           12732 :     reset_on_dsm_detach();
     418           12732 : }
     419                 : 
     420                 : /* ----------------------------------------------------------------
     421                 :  *      check_on_shmem_exit_lists_are_empty
     422                 :  *
     423                 :  *      Debugging check that no shmem cleanup handlers have been registered
     424                 :  *      prematurely in the current process.
     425                 :  * ----------------------------------------------------------------
     426                 :  */
     427                 : void
     428            8654 : check_on_shmem_exit_lists_are_empty(void)
     429                 : {
     430            8654 :     if (before_shmem_exit_index)
     431 UBC           0 :         elog(FATAL, "before_shmem_exit has been called prematurely");
     432 CBC        8654 :     if (on_shmem_exit_index)
     433 UBC           0 :         elog(FATAL, "on_shmem_exit has been called prematurely");
     434                 :     /* Checking DSM detach state seems unnecessary given the above */
     435 CBC        8654 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a