LCOV - differential code coverage report
Current view: top level - src/backend/postmaster - startup.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 86.4 % 110 95 15 1 94 1
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 16 16 1 15
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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-2023, PostgreSQL Global Development Group
      13                 :  *
      14                 :  *
      15                 :  * IDENTIFICATION
      16                 :  *    src/backend/postmaster/startup.c
      17                 :  *
      18                 :  *-------------------------------------------------------------------------
      19                 :  */
      20                 : #include "postgres.h"
      21                 : 
      22                 : #include "access/xlog.h"
      23                 : #include "access/xlogrecovery.h"
      24                 : #include "access/xlogutils.h"
      25                 : #include "libpq/pqsignal.h"
      26                 : #include "miscadmin.h"
      27                 : #include "pgstat.h"
      28                 : #include "postmaster/interrupt.h"
      29                 : #include "postmaster/startup.h"
      30                 : #include "storage/ipc.h"
      31                 : #include "storage/latch.h"
      32                 : #include "storage/pmsignal.h"
      33                 : #include "storage/procsignal.h"
      34                 : #include "storage/standby.h"
      35                 : #include "utils/guc.h"
      36                 : #include "utils/memutils.h"
      37                 : #include "utils/timeout.h"
      38                 : 
      39                 : 
      40                 : #ifndef USE_POSTMASTER_DEATH_SIGNAL
      41                 : /*
      42                 :  * On systems that need to make a system call to find out if the postmaster has
      43                 :  * gone away, we'll do so only every Nth call to HandleStartupProcInterrupts().
      44                 :  * This only affects how long it takes us to detect the condition while we're
      45                 :  * busy replaying WAL.  Latch waits and similar which should react immediately
      46                 :  * through the usual techniques.
      47                 :  */
      48                 : #define POSTMASTER_POLL_RATE_LIMIT 1024
      49                 : #endif
      50                 : 
      51                 : /*
      52                 :  * Flags set by interrupt handlers for later service in the redo loop.
      53                 :  */
      54                 : static volatile sig_atomic_t got_SIGHUP = false;
      55                 : static volatile sig_atomic_t shutdown_requested = false;
      56                 : static volatile sig_atomic_t promote_signaled = false;
      57                 : 
      58                 : /*
      59                 :  * Flag set when executing a restore command, to tell SIGTERM signal handler
      60                 :  * that it's safe to just proc_exit.
      61                 :  */
      62                 : static volatile sig_atomic_t in_restore_command = false;
      63                 : 
      64                 : /*
      65                 :  * Time at which the most recent startup operation started.
      66                 :  */
      67                 : static TimestampTz startup_progress_phase_start_time;
      68                 : 
      69                 : /*
      70                 :  * Indicates whether the startup progress interval mentioned by the user is
      71                 :  * elapsed or not. TRUE if timeout occurred, FALSE otherwise.
      72                 :  */
      73                 : static volatile sig_atomic_t startup_progress_timer_expired = false;
      74                 : 
      75                 : /*
      76                 :  * Time between progress updates for long-running startup operations.
      77                 :  */
      78                 : int         log_startup_progress_interval = 10000;  /* 10 sec */
      79                 : 
      80                 : /* Signal handlers */
      81                 : static void StartupProcTriggerHandler(SIGNAL_ARGS);
      82                 : static void StartupProcSigHupHandler(SIGNAL_ARGS);
      83                 : 
      84                 : /* Callbacks */
      85                 : static void StartupProcExit(int code, Datum arg);
      86                 : 
      87                 : 
      88                 : /* --------------------------------
      89                 :  *      signal handler routines
      90                 :  * --------------------------------
      91                 :  */
      92                 : 
      93                 : /* SIGUSR2: set flag to finish recovery */
      94                 : static void
      95 CBC          36 : StartupProcTriggerHandler(SIGNAL_ARGS)
      96                 : {
      97              36 :     int         save_errno = errno;
      98                 : 
      99              36 :     promote_signaled = true;
     100              36 :     WakeupRecovery();
     101                 : 
     102              36 :     errno = save_errno;
     103              36 : }
     104                 : 
     105                 : /* SIGHUP: set flag to re-read config file at next convenient time */
     106                 : static void
     107              14 : StartupProcSigHupHandler(SIGNAL_ARGS)
     108                 : {
     109              14 :     int         save_errno = errno;
     110                 : 
     111              14 :     got_SIGHUP = true;
     112              14 :     WakeupRecovery();
     113                 : 
     114              14 :     errno = save_errno;
     115              14 : }
     116                 : 
     117                 : /* SIGTERM: set flag to abort redo and exit */
     118                 : static void
     119              31 : StartupProcShutdownHandler(SIGNAL_ARGS)
     120                 : {
     121              31 :     int         save_errno = errno;
     122                 : 
     123              31 :     if (in_restore_command)
     124 UBC           0 :         proc_exit(1);
     125                 :     else
     126 CBC          31 :         shutdown_requested = true;
     127              31 :     WakeupRecovery();
     128                 : 
     129              31 :     errno = save_errno;
     130              31 : }
     131                 : 
     132                 : /*
     133                 :  * Re-read the config file.
     134                 :  *
     135                 :  * If one of the critical walreceiver options has changed, flag xlog.c
     136                 :  * to restart it.
     137                 :  */
     138                 : static void
     139              14 : StartupRereadConfig(void)
     140                 : {
     141              14 :     char       *conninfo = pstrdup(PrimaryConnInfo);
     142              14 :     char       *slotname = pstrdup(PrimarySlotName);
     143              14 :     bool        tempSlot = wal_receiver_create_temp_slot;
     144                 :     bool        conninfoChanged;
     145                 :     bool        slotnameChanged;
     146              14 :     bool        tempSlotChanged = false;
     147                 : 
     148              14 :     ProcessConfigFile(PGC_SIGHUP);
     149                 : 
     150              14 :     conninfoChanged = strcmp(conninfo, PrimaryConnInfo) != 0;
     151              14 :     slotnameChanged = strcmp(slotname, PrimarySlotName) != 0;
     152                 : 
     153                 :     /*
     154                 :      * wal_receiver_create_temp_slot is used only when we have no slot
     155                 :      * configured.  We do not need to track this change if it has no effect.
     156                 :      */
     157              14 :     if (!slotnameChanged && strcmp(PrimarySlotName, "") == 0)
     158               3 :         tempSlotChanged = tempSlot != wal_receiver_create_temp_slot;
     159              14 :     pfree(conninfo);
     160              14 :     pfree(slotname);
     161                 : 
     162              14 :     if (conninfoChanged || slotnameChanged || tempSlotChanged)
     163 UBC           0 :         StartupRequestWalReceiverRestart();
     164 CBC          14 : }
     165                 : 
     166                 : /* Handle various signals that might be sent to the startup process */
     167                 : void
     168         2517486 : HandleStartupProcInterrupts(void)
     169                 : {
     170                 : #ifdef POSTMASTER_POLL_RATE_LIMIT
     171                 :     static uint32 postmaster_poll_count = 0;
     172                 : #endif
     173                 : 
     174                 :     /*
     175                 :      * Process any requests or signals received recently.
     176                 :      */
     177         2517486 :     if (got_SIGHUP)
     178                 :     {
     179              14 :         got_SIGHUP = false;
     180              14 :         StartupRereadConfig();
     181                 :     }
     182                 : 
     183                 :     /*
     184                 :      * Check if we were requested to exit without finishing recovery.
     185                 :      */
     186         2517486 :     if (shutdown_requested)
     187              31 :         proc_exit(1);
     188                 : 
     189                 :     /*
     190                 :      * Emergency bailout if postmaster has died.  This is to avoid the
     191                 :      * necessity for manual cleanup of all postmaster children.  Do this less
     192                 :      * frequently on systems for which we don't have signals to make that
     193                 :      * cheap.
     194                 :      */
     195         2517455 :     if (IsUnderPostmaster &&
     196                 : #ifdef POSTMASTER_POLL_RATE_LIMIT
     197                 :         postmaster_poll_count++ % POSTMASTER_POLL_RATE_LIMIT == 0 &&
     198                 : #endif
     199         2491932 :         !PostmasterIsAlive())
     200 UBC           0 :         exit(1);
     201                 : 
     202                 :     /* Process barrier events */
     203 CBC     2517455 :     if (ProcSignalBarrierPending)
     204 UBC           0 :         ProcessProcSignalBarrier();
     205                 : 
     206                 :     /* Perform logging of memory contexts of this process */
     207 CBC     2517455 :     if (LogMemoryContextPending)
     208 UBC           0 :         ProcessLogMemoryContextInterrupt();
     209 CBC     2517455 : }
     210                 : 
     211                 : 
     212                 : /* --------------------------------
     213                 :  *      signal handler routines
     214                 :  * --------------------------------
     215                 :  */
     216                 : static void
     217             557 : StartupProcExit(int code, Datum arg)
     218                 : {
     219                 :     /* Shutdown the recovery environment */
     220             557 :     if (standbyState != STANDBY_DISABLED)
     221              71 :         ShutdownRecoveryTransactionEnvironment();
     222             557 : }
     223                 : 
     224                 : 
     225                 : /* ----------------------------------
     226                 :  *  Startup Process main entry point
     227                 :  * ----------------------------------
     228                 :  */
     229                 : void
     230             557 : StartupProcessMain(void)
     231                 : {
     232                 :     /* Arrange to clean up at startup process exit */
     233             557 :     on_shmem_exit(StartupProcExit, 0);
     234                 : 
     235                 :     /*
     236                 :      * Properly accept or ignore signals the postmaster might send us.
     237                 :      */
     238             557 :     pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
     239             557 :     pqsignal(SIGINT, SIG_IGN);  /* ignore query cancel */
     240             557 :     pqsignal(SIGTERM, StartupProcShutdownHandler);  /* request shutdown */
     241                 :     /* SIGQUIT handler was already set up by InitPostmasterChild */
     242             557 :     InitializeTimeouts();       /* establishes SIGALRM handler */
     243             557 :     pqsignal(SIGPIPE, SIG_IGN);
     244             557 :     pqsignal(SIGUSR1, procsignal_sigusr1_handler);
     245             557 :     pqsignal(SIGUSR2, StartupProcTriggerHandler);
     246                 : 
     247                 :     /*
     248                 :      * Reset some signals that are accepted by postmaster but not here
     249                 :      */
     250             557 :     pqsignal(SIGCHLD, SIG_DFL);
     251                 : 
     252                 :     /*
     253                 :      * Register timeouts needed for standby mode
     254                 :      */
     255             557 :     RegisterTimeout(STANDBY_DEADLOCK_TIMEOUT, StandbyDeadLockHandler);
     256             557 :     RegisterTimeout(STANDBY_TIMEOUT, StandbyTimeoutHandler);
     257             557 :     RegisterTimeout(STANDBY_LOCK_TIMEOUT, StandbyLockTimeoutHandler);
     258                 : 
     259                 :     /*
     260                 :      * Unblock signals (they were blocked when the postmaster forked us)
     261                 :      */
     262 GNC         557 :     sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
     263                 : 
     264                 :     /*
     265                 :      * Do what we came for.
     266                 :      */
     267 CBC         557 :     StartupXLOG();
     268                 : 
     269                 :     /*
     270                 :      * Exit normally. Exit code 0 tells postmaster that we completed recovery
     271                 :      * successfully.
     272                 :      */
     273             523 :     proc_exit(0);
     274                 : }
     275                 : 
     276                 : void
     277             131 : PreRestoreCommand(void)
     278                 : {
     279                 :     /*
     280                 :      * Set in_restore_command to tell the signal handler that we should exit
     281                 :      * right away on SIGTERM. We know that we're at a safe point to do that.
     282                 :      * Check if we had already received the signal, so that we don't miss a
     283                 :      * shutdown request received just before this.
     284                 :      */
     285             131 :     in_restore_command = true;
     286             131 :     if (shutdown_requested)
     287 UBC           0 :         proc_exit(1);
     288 CBC         131 : }
     289                 : 
     290                 : void
     291             131 : PostRestoreCommand(void)
     292                 : {
     293             131 :     in_restore_command = false;
     294             131 : }
     295                 : 
     296                 : bool
     297           13211 : IsPromoteSignaled(void)
     298                 : {
     299           13211 :     return promote_signaled;
     300                 : }
     301                 : 
     302                 : void
     303              36 : ResetPromoteSignaled(void)
     304                 : {
     305              36 :     promote_signaled = false;
     306              36 : }
     307                 : 
     308                 : /*
     309                 :  * Set a flag indicating that it's time to log a progress report.
     310                 :  */
     311                 : void
     312              10 : startup_progress_timeout_handler(void)
     313                 : {
     314              10 :     startup_progress_timer_expired = true;
     315              10 : }
     316                 : 
     317                 : void
     318             414 : disable_startup_progress_timeout(void)
     319                 : {
     320                 :     /* Feature is disabled. */
     321             414 :     if (log_startup_progress_interval == 0)
     322 UBC           0 :         return;
     323                 : 
     324 CBC         414 :     disable_timeout(STARTUP_PROGRESS_TIMEOUT, false);
     325             414 :     startup_progress_timer_expired = false;
     326                 : }
     327                 : 
     328                 : /*
     329                 :  * Set the start timestamp of the current operation and enable the timeout.
     330                 :  */
     331                 : void
     332             346 : enable_startup_progress_timeout(void)
     333                 : {
     334                 :     TimestampTz fin_time;
     335                 : 
     336                 :     /* Feature is disabled. */
     337             346 :     if (log_startup_progress_interval == 0)
     338 UBC           0 :         return;
     339                 : 
     340 CBC         346 :     startup_progress_phase_start_time = GetCurrentTimestamp();
     341             346 :     fin_time = TimestampTzPlusMilliseconds(startup_progress_phase_start_time,
     342                 :                                            log_startup_progress_interval);
     343             346 :     enable_timeout_every(STARTUP_PROGRESS_TIMEOUT, fin_time,
     344                 :                          log_startup_progress_interval);
     345                 : }
     346                 : 
     347                 : /*
     348                 :  * A thin wrapper to first disable and then enable the startup progress
     349                 :  * timeout.
     350                 :  */
     351                 : void
     352             346 : begin_startup_progress_phase(void)
     353                 : {
     354                 :     /* Feature is disabled. */
     355             346 :     if (log_startup_progress_interval == 0)
     356 UBC           0 :         return;
     357                 : 
     358 CBC         346 :     disable_startup_progress_timeout();
     359             346 :     enable_startup_progress_timeout();
     360                 : }
     361                 : 
     362                 : /*
     363                 :  * Report whether startup progress timeout has occurred. Reset the timer flag
     364                 :  * if it did, set the elapsed time to the out parameters and return true,
     365                 :  * otherwise return false.
     366                 :  */
     367                 : bool
     368          239346 : has_startup_progress_timeout_expired(long *secs, int *usecs)
     369                 : {
     370                 :     long        seconds;
     371                 :     int         useconds;
     372                 :     TimestampTz now;
     373                 : 
     374                 :     /* No timeout has occurred. */
     375          239346 :     if (!startup_progress_timer_expired)
     376          239346 :         return false;
     377                 : 
     378                 :     /* Calculate the elapsed time. */
     379 UBC           0 :     now = GetCurrentTimestamp();
     380               0 :     TimestampDifference(startup_progress_phase_start_time, now, &seconds, &useconds);
     381                 : 
     382               0 :     *secs = seconds;
     383               0 :     *usecs = useconds;
     384               0 :     startup_progress_timer_expired = false;
     385                 : 
     386               0 :     return true;
     387                 : }
        

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