@@ -65,8 +65,8 @@ typedef struct
6565 pg_atomic_uint32 pss_pid ;
6666 int pss_cancel_key_len ; /* 0 means no cancellation is possible */
6767 uint8 pss_cancel_key [MAX_CANCEL_KEY_LENGTH ];
68- volatile sig_atomic_t pss_signalFlags [ NUM_PROCSIGNALS ];
69- slock_t pss_mutex ; /* protects the above fields */
68+ pg_atomic_uint32 pss_signalFlags ; /* bitmask of pending signals */
69+ slock_t pss_mutex ; /* protects cancel_key fields only */
7070
7171 /* Barrier-related fields (not protected by pss_mutex) */
7272 pg_atomic_uint64 pss_barrierGeneration ;
@@ -105,7 +105,7 @@ struct ProcSignalHeader
105105NON_EXEC_STATIC ProcSignalHeader * ProcSignal = NULL ;
106106static ProcSignalSlot * MyProcSignalSlot = NULL ;
107107
108- static bool CheckProcSignal ( ProcSignalReason reason );
108+ static bool HasProcSignalFlag ( uint32 flags , ProcSignalReason reason );
109109static void CleanupProcSignalState (int status , Datum arg );
110110static void ResetProcSignalBarrierBits (uint32 flags );
111111
@@ -150,7 +150,7 @@ ProcSignalShmemInit(void)
150150 SpinLockInit (& slot -> pss_mutex );
151151 pg_atomic_init_u32 (& slot -> pss_pid , 0 );
152152 slot -> pss_cancel_key_len = 0 ;
153- MemSet ( slot -> pss_signalFlags , 0 , sizeof ( slot -> pss_signalFlags ) );
153+ pg_atomic_init_u32 ( & slot -> pss_signalFlags , 0 );
154154 pg_atomic_init_u64 (& slot -> pss_barrierGeneration , PG_UINT64_MAX );
155155 pg_atomic_init_u32 (& slot -> pss_barrierCheckMask , 0 );
156156 ConditionVariableInit (& slot -> pss_barrierCV );
@@ -182,7 +182,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len)
182182 old_pss_pid = pg_atomic_read_u32 (& slot -> pss_pid );
183183
184184 /* Clear out any leftover signal reasons */
185- MemSet ( slot -> pss_signalFlags , 0 , NUM_PROCSIGNALS * sizeof ( sig_atomic_t ) );
185+ pg_atomic_write_u32 ( & slot -> pss_signalFlags , 0 );
186186
187187 /*
188188 * Initialize barrier state. Since we're a brand-new process, there
@@ -212,7 +212,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len)
212212 elog (LOG , "process %d taking over ProcSignal slot %d, but it's not empty" ,
213213 MyProcPid , MyProcNumber );
214214
215- /* Remember slot location for CheckProcSignal */
215+ /* Remember slot location for HasProcSignalFlag */
216216 MyProcSignalSlot = slot ;
217217
218218 /* Set up to release the slot on process exit */
@@ -294,10 +294,15 @@ SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
294294 if (pg_atomic_read_u32 (& slot -> pss_pid ) == pid )
295295 {
296296 /* Atomically set the proper flag */
297- slot -> pss_signalFlags [reason ] = true;
297+ uint32 oldflags = pg_atomic_fetch_or_u32 (& slot -> pss_signalFlags ,
298+ (uint32 ) 1 << reason );
299+
298300 SpinLockRelease (& slot -> pss_mutex );
299- /* Send signal */
300- return kill (pid , SIGUSR1 );
301+ /* Send signal only if there were no pending signals before this. */
302+ if (oldflags == 0 )
303+ return kill (pid , SIGUSR1 );
304+ else
305+ return 0 ;
301306 }
302307 SpinLockRelease (& slot -> pss_mutex );
303308 }
@@ -322,10 +327,15 @@ SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
322327 if (pg_atomic_read_u32 (& slot -> pss_pid ) == pid )
323328 {
324329 /* Atomically set the proper flag */
325- slot -> pss_signalFlags [reason ] = true;
330+ uint32 oldflags = pg_atomic_fetch_or_u32 (& slot -> pss_signalFlags ,
331+ (uint32 ) 1 << reason );
332+
326333 SpinLockRelease (& slot -> pss_mutex );
327- /* Send signal */
328- return kill (pid , SIGUSR1 );
334+ /* Send signal only if there were no pending signals before this. */
335+ if (oldflags == 0 )
336+ return kill (pid , SIGUSR1 );
337+ else
338+ return 0 ;
329339 }
330340 SpinLockRelease (& slot -> pss_mutex );
331341 }
@@ -404,9 +414,13 @@ EmitProcSignalBarrier(ProcSignalBarrierType type)
404414 if (pid != 0 )
405415 {
406416 /* see SendProcSignal for details */
407- slot -> pss_signalFlags [PROCSIG_BARRIER ] = true;
417+ uint32 oldflags = pg_atomic_fetch_or_u32 (& slot -> pss_signalFlags ,
418+ (uint32 ) 1 << PROCSIG_BARRIER );
419+
408420 SpinLockRelease (& slot -> pss_mutex );
409- kill (pid , SIGUSR1 );
421+ /* Send signal only if there were no pending signals before this. */
422+ if (oldflags == 0 )
423+ kill (pid , SIGUSR1 );
410424 }
411425 else
412426 SpinLockRelease (& slot -> pss_mutex );
@@ -641,30 +655,13 @@ ResetProcSignalBarrierBits(uint32 flags)
641655}
642656
643657/*
644- * CheckProcSignal - check to see if a particular reason has been
645- * signaled, and clear the signal flag. Should be called after receiving
646- * SIGUSR1.
658+ * HasProcSignalFlag - check to see if a particular reason has been
659+ * signaled in the given flags bitmask.
647660 */
648661static bool
649- CheckProcSignal ( ProcSignalReason reason )
662+ HasProcSignalFlag ( uint32 flags , ProcSignalReason reason )
650663{
651- volatile ProcSignalSlot * slot = MyProcSignalSlot ;
652-
653- if (slot != NULL )
654- {
655- /*
656- * Careful here --- don't clear flag if we haven't seen it set.
657- * pss_signalFlags is of type "volatile sig_atomic_t" to allow us to
658- * read it here safely, without holding the spinlock.
659- */
660- if (slot -> pss_signalFlags [reason ])
661- {
662- slot -> pss_signalFlags [reason ] = false;
663- return true;
664- }
665- }
666-
667- return false;
664+ return (flags & ((uint32 ) 1 << reason )) != 0 ;
668665}
669666
670667/*
@@ -673,46 +670,54 @@ CheckProcSignal(ProcSignalReason reason)
673670void
674671procsignal_sigusr1_handler (SIGNAL_ARGS )
675672{
676- if (CheckProcSignal (PROCSIG_CATCHUP_INTERRUPT ))
673+ uint32 flags ;
674+
675+ /* Atomically consume all pending signals */
676+ if (MyProcSignalSlot )
677+ flags = pg_atomic_exchange_u32 (& MyProcSignalSlot -> pss_signalFlags , 0 );
678+ else
679+ flags = 0 ;
680+
681+ if (HasProcSignalFlag (flags , PROCSIG_CATCHUP_INTERRUPT ))
677682 HandleCatchupInterrupt ();
678683
679- if (CheckProcSignal ( PROCSIG_NOTIFY_INTERRUPT ))
684+ if (HasProcSignalFlag ( flags , PROCSIG_NOTIFY_INTERRUPT ))
680685 HandleNotifyInterrupt ();
681686
682- if (CheckProcSignal ( PROCSIG_PARALLEL_MESSAGE ))
687+ if (HasProcSignalFlag ( flags , PROCSIG_PARALLEL_MESSAGE ))
683688 HandleParallelMessageInterrupt ();
684689
685- if (CheckProcSignal ( PROCSIG_WALSND_INIT_STOPPING ))
690+ if (HasProcSignalFlag ( flags , PROCSIG_WALSND_INIT_STOPPING ))
686691 HandleWalSndInitStopping ();
687692
688- if (CheckProcSignal ( PROCSIG_BARRIER ))
693+ if (HasProcSignalFlag ( flags , PROCSIG_BARRIER ))
689694 HandleProcSignalBarrierInterrupt ();
690695
691- if (CheckProcSignal ( PROCSIG_LOG_MEMORY_CONTEXT ))
696+ if (HasProcSignalFlag ( flags , PROCSIG_LOG_MEMORY_CONTEXT ))
692697 HandleLogMemoryContextInterrupt ();
693698
694- if (CheckProcSignal ( PROCSIG_PARALLEL_APPLY_MESSAGE ))
699+ if (HasProcSignalFlag ( flags , PROCSIG_PARALLEL_APPLY_MESSAGE ))
695700 HandleParallelApplyMessageInterrupt ();
696701
697- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_DATABASE ))
702+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_DATABASE ))
698703 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_DATABASE );
699704
700- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_TABLESPACE ))
705+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_TABLESPACE ))
701706 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_TABLESPACE );
702707
703- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_LOCK ))
708+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_LOCK ))
704709 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_LOCK );
705710
706- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_SNAPSHOT ))
711+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_SNAPSHOT ))
707712 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_SNAPSHOT );
708713
709- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT ))
714+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT ))
710715 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT );
711716
712- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK ))
717+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK ))
713718 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK );
714719
715- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_BUFFERPIN ))
720+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_BUFFERPIN ))
716721 HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_BUFFERPIN );
717722
718723 SetLatch (MyLatch );
0 commit comments