Skip to content

Commit b8f1647

Browse files
joelonsqlCommitfest Bot
authored andcommitted
Optimize LISTEN/NOTIFY wakeup by replacing signal with direct SetLatch
Building upon the robust atomic state machine introduced in the previous commit, this change completes the modernization of NOTIFY IPC by replacing its wakeup mechanism. With inter-process state now managed reliably, the heavyweight SIGUSR1 signal is no longer necessary and is replaced with a much more efficient, direct "poke." The async.c notifier now replaces its call to SendProcSignal with a direct call to SetLatch on the target backend's procLatch. This is a significant optimization because WaitLatch, which listeners already use for blocking, is underpinned by the modern WaitEventSet abstraction (kqueue, epoll, etc.). We now leverage this existing, highly efficient infrastructure for the wakeup, completely bypassing the kill() syscall and the SIGUSR1 signal handler for all NOTIFY events. This demonstrates a powerful, two-step migration pattern: 1. First, solve a subsystem's state synchronization problem with a lock-free, atomic FSM to eliminate redundant signaling. 2. Then, with state management handled, make the wakeup itself cheaper by replacing the expensive signal with a direct SetLatch. This staged approach allows us to modernize subsystems incrementally and safely. By applying this pattern to async.c, we prove its viability and simplicity, creating a clear template for other parts of the system to follow in moving towards a more performant, signal-free IPC model.
1 parent a54954c commit b8f1647

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

src/backend/commands/async.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@
142142
#include "miscadmin.h"
143143
#include "storage/ipc.h"
144144
#include "storage/lmgr.h"
145+
#include "storage/proc.h"
145146
#include "storage/procsignal.h"
146147
#include "tcop/tcopprot.h"
147148
#include "utils/builtins.h"
@@ -1719,13 +1720,25 @@ SignalBackends(void)
17191720
else
17201721
{
17211722
/*
1722-
* Note: assuming things aren't broken, a signal failure here could
1723-
* only occur if the target backend exited since we released
1724-
* NotifyQueueLock; which is unlikely but certainly possible. So we
1725-
* just log a low-level debug message if it happens.
1723+
* Get the target backend's PGPROC and set its latch.
1724+
*
1725+
* Note: The target backend might exit after we released
1726+
* NotifyQueueLock but before we set the latch. We need to
1727+
* handle the race condition where the PGPROC slot might be
1728+
* recycled by a new process with a different PID.
17261729
*/
1727-
if (SendProcSignal(pid, PROCSIG_NOTIFY_INTERRUPT, procno) < 0)
1728-
elog(DEBUG3, "could not signal backend with PID %d: %m", pid);
1730+
PGPROC *proc = GetPGProcByNumber(procno);
1731+
1732+
/* Verify the PID hasn't changed (backend hasn't exited) */
1733+
if (proc->pid == pid)
1734+
{
1735+
SetLatch(&proc->procLatch);
1736+
}
1737+
else
1738+
{
1739+
/* Backend exited and slot was recycled */
1740+
elog(DEBUG3, "could not signal backend with PID %d: process no longer exists", pid);
1741+
}
17291742
}
17301743
}
17311744
}

0 commit comments

Comments
 (0)