115115#include "postmaster/syslogger.h"
116116#include "postmaster/walsummarizer.h"
117117#include "replication/logicallauncher.h"
118+ #include "replication/slotsync.h"
118119#include "replication/walsender.h"
119120#include "storage/fd.h"
120121#include "storage/ipc.h"
167168 * they will never become live backends. dead_end children are not assigned a
168169 * PMChildSlot. dead_end children have bkend_type NORMAL.
169170 *
170- * "Special" children such as the startup, bgwriter and autovacuum launcher
171- * tasks are not in this list. They are tracked via StartupPID and other
172- * pid_t variables below. (Thus, there can't be more than one of any given
173- * "special" child process type. We use BackendList entries for any child
174- * process there can be more than one of.)
171+ * "Special" children such as the startup, bgwriter, autovacuum launcher, and
172+ * slot sync worker tasks are not in this list. They are tracked via StartupPID
173+ * and other pid_t variables below. (Thus, there can't be more than one of any
174+ * given "special" child process type. We use BackendList entries for any
175+ * child process there can be more than one of.)
175176 */
176177typedef struct bkend
177178{
@@ -254,7 +255,8 @@ static pid_t StartupPID = 0,
254255 WalSummarizerPID = 0 ,
255256 AutoVacPID = 0 ,
256257 PgArchPID = 0 ,
257- SysLoggerPID = 0 ;
258+ SysLoggerPID = 0 ,
259+ SlotSyncWorkerPID = 0 ;
258260
259261/* Startup process's status */
260262typedef enum
@@ -445,6 +447,7 @@ static void StartAutovacuumWorker(void);
445447static void MaybeStartWalReceiver (void );
446448static void MaybeStartWalSummarizer (void );
447449static void InitPostmasterDeathWatchHandle (void );
450+ static void MaybeStartSlotSyncWorker (void );
448451
449452/*
450453 * Archiver is allowed to start up at the current postmaster state?
@@ -1822,6 +1825,9 @@ ServerLoop(void)
18221825 if (PgArchPID == 0 && PgArchStartupAllowed ())
18231826 PgArchPID = StartChildProcess (ArchiverProcess );
18241827
1828+ /* If we need to start a slot sync worker, try to do that now */
1829+ MaybeStartSlotSyncWorker ();
1830+
18251831 /* If we need to signal the autovacuum launcher, do so now */
18261832 if (avlauncher_needs_signal )
18271833 {
@@ -2661,6 +2667,8 @@ process_pm_reload_request(void)
26612667 signal_child (PgArchPID , SIGHUP );
26622668 if (SysLoggerPID != 0 )
26632669 signal_child (SysLoggerPID , SIGHUP );
2670+ if (SlotSyncWorkerPID != 0 )
2671+ signal_child (SlotSyncWorkerPID , SIGHUP );
26642672
26652673 /* Reload authentication config files too */
26662674 if (!load_hba ())
@@ -3010,6 +3018,7 @@ process_pm_child_exit(void)
30103018 AutoVacPID = StartAutoVacLauncher ();
30113019 if (PgArchStartupAllowed () && PgArchPID == 0 )
30123020 PgArchPID = StartChildProcess (ArchiverProcess );
3021+ MaybeStartSlotSyncWorker ();
30133022
30143023 /* workers may be scheduled to start now */
30153024 maybe_start_bgworkers ();
@@ -3180,6 +3189,22 @@ process_pm_child_exit(void)
31803189 continue ;
31813190 }
31823191
3192+ /*
3193+ * Was it the slot sync worker? Normal exit or FATAL exit can be
3194+ * ignored (FATAL can be caused by libpqwalreceiver on receiving
3195+ * shutdown request by the startup process during promotion); we'll
3196+ * start a new one at the next iteration of the postmaster's main
3197+ * loop, if necessary. Any other exit condition is treated as a crash.
3198+ */
3199+ if (pid == SlotSyncWorkerPID )
3200+ {
3201+ SlotSyncWorkerPID = 0 ;
3202+ if (!EXIT_STATUS_0 (exitstatus ) && !EXIT_STATUS_1 (exitstatus ))
3203+ HandleChildCrash (pid , exitstatus ,
3204+ _ ("slot sync worker process" ));
3205+ continue ;
3206+ }
3207+
31833208 /* Was it one of our background workers? */
31843209 if (CleanupBackgroundWorker (pid , exitstatus ))
31853210 {
@@ -3384,7 +3409,7 @@ CleanupBackend(int pid,
33843409
33853410/*
33863411 * HandleChildCrash -- cleanup after failed backend, bgwriter, checkpointer,
3387- * walwriter, autovacuum, archiver or background worker.
3412+ * walwriter, autovacuum, archiver, slot sync worker, or background worker.
33883413 *
33893414 * The objectives here are to clean up our local state about the child
33903415 * process, and to signal all other remaining children to quickdie.
@@ -3546,6 +3571,12 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
35463571 else if (PgArchPID != 0 && take_action )
35473572 sigquit_child (PgArchPID );
35483573
3574+ /* Take care of the slot sync worker too */
3575+ if (pid == SlotSyncWorkerPID )
3576+ SlotSyncWorkerPID = 0 ;
3577+ else if (SlotSyncWorkerPID != 0 && take_action )
3578+ sigquit_child (SlotSyncWorkerPID );
3579+
35493580 /* We do NOT restart the syslogger */
35503581
35513582 if (Shutdown != ImmediateShutdown )
@@ -3686,6 +3717,8 @@ PostmasterStateMachine(void)
36863717 signal_child (WalReceiverPID , SIGTERM );
36873718 if (WalSummarizerPID != 0 )
36883719 signal_child (WalSummarizerPID , SIGTERM );
3720+ if (SlotSyncWorkerPID != 0 )
3721+ signal_child (SlotSyncWorkerPID , SIGTERM );
36893722 /* checkpointer, archiver, stats, and syslogger may continue for now */
36903723
36913724 /* Now transition to PM_WAIT_BACKENDS state to wait for them to die */
@@ -3701,13 +3734,13 @@ PostmasterStateMachine(void)
37013734 /*
37023735 * PM_WAIT_BACKENDS state ends when we have no regular backends
37033736 * (including autovac workers), no bgworkers (including unconnected
3704- * ones), and no walwriter, autovac launcher or bgwriter. If we are
3705- * doing crash recovery or an immediate shutdown then we expect the
3706- * checkpointer to exit as well, otherwise not. The stats and
3707- * syslogger processes are disregarded since they are not connected to
3708- * shared memory; we also disregard dead_end children here. Walsenders
3709- * and archiver are also disregarded, they will be terminated later
3710- * after writing the checkpoint record.
3737+ * ones), and no walwriter, autovac launcher, bgwriter or slot sync
3738+ * worker. If we are doing crash recovery or an immediate shutdown
3739+ * then we expect the checkpointer to exit as well, otherwise not. The
3740+ * stats and syslogger processes are disregarded since they are not
3741+ * connected to shared memory; we also disregard dead_end children
3742+ * here. Walsenders and archiver are also disregarded, they will be
3743+ * terminated later after writing the checkpoint record.
37113744 */
37123745 if (CountChildren (BACKEND_TYPE_ALL - BACKEND_TYPE_WALSND ) == 0 &&
37133746 StartupPID == 0 &&
@@ -3717,7 +3750,8 @@ PostmasterStateMachine(void)
37173750 (CheckpointerPID == 0 ||
37183751 (!FatalError && Shutdown < ImmediateShutdown )) &&
37193752 WalWriterPID == 0 &&
3720- AutoVacPID == 0 )
3753+ AutoVacPID == 0 &&
3754+ SlotSyncWorkerPID == 0 )
37213755 {
37223756 if (Shutdown >= ImmediateShutdown || FatalError )
37233757 {
@@ -3815,6 +3849,7 @@ PostmasterStateMachine(void)
38153849 Assert (CheckpointerPID == 0 );
38163850 Assert (WalWriterPID == 0 );
38173851 Assert (AutoVacPID == 0 );
3852+ Assert (SlotSyncWorkerPID == 0 );
38183853 /* syslogger is not considered here */
38193854 pmState = PM_NO_CHILDREN ;
38203855 }
@@ -4038,6 +4073,8 @@ TerminateChildren(int signal)
40384073 signal_child (AutoVacPID , signal );
40394074 if (PgArchPID != 0 )
40404075 signal_child (PgArchPID , signal );
4076+ if (SlotSyncWorkerPID != 0 )
4077+ signal_child (SlotSyncWorkerPID , signal );
40414078}
40424079
40434080/*
@@ -4850,6 +4887,7 @@ SubPostmasterMain(int argc, char *argv[])
48504887 */
48514888 if (strcmp (argv [1 ], "--forkbackend" ) == 0 ||
48524889 strcmp (argv [1 ], "--forkavlauncher" ) == 0 ||
4890+ strcmp (argv [1 ], "--forkssworker" ) == 0 ||
48534891 strcmp (argv [1 ], "--forkavworker" ) == 0 ||
48544892 strcmp (argv [1 ], "--forkaux" ) == 0 ||
48554893 strcmp (argv [1 ], "--forkbgworker" ) == 0 )
@@ -4953,6 +4991,13 @@ SubPostmasterMain(int argc, char *argv[])
49534991
49544992 AutoVacWorkerMain (argc - 2 , argv + 2 ); /* does not return */
49554993 }
4994+ if (strcmp (argv [1 ], "--forkssworker" ) == 0 )
4995+ {
4996+ /* Restore basic shared memory pointers */
4997+ InitShmemAccess (UsedShmemSegAddr );
4998+
4999+ ReplSlotSyncWorkerMain (argc - 2 , argv + 2 ); /* does not return */
5000+ }
49565001 if (strcmp (argv [1 ], "--forkbgworker" ) == 0 )
49575002 {
49585003 /* do this as early as possible; in particular, before InitProcess() */
@@ -5498,6 +5543,24 @@ MaybeStartWalSummarizer(void)
54985543}
54995544
55005545
5546+ /*
5547+ * MaybeStartSlotSyncWorker
5548+ * Start the slot sync worker, if not running and our state allows.
5549+ *
5550+ * We allow to start the slot sync worker when we are on a hot standby,
5551+ * fast or immediate shutdown is not in progress, slot sync parameters
5552+ * are configured correctly, and it is the first time of worker's launch,
5553+ * or enough time has passed since the worker was launched last.
5554+ */
5555+ static void
5556+ MaybeStartSlotSyncWorker (void )
5557+ {
5558+ if (SlotSyncWorkerPID == 0 && pmState == PM_HOT_STANDBY &&
5559+ Shutdown <= SmartShutdown && sync_replication_slots &&
5560+ ValidateSlotSyncParams (LOG ) && SlotSyncWorkerCanRestart ())
5561+ SlotSyncWorkerPID = StartSlotSyncWorker ();
5562+ }
5563+
55015564/*
55025565 * Create the opts file
55035566 */
0 commit comments