#include "miscadmin.h"
#include "pgstat.h"
#include "replication/walreceiver.h"
+#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/proc.h"
#include "storage/shmem.h"
struct WaitLSNState *waitLSNState = NULL;
+static bool waitLSNShmemExitRegistered = false;
+
static void WaitLSNShmemRequest(void *arg);
static void WaitLSNShmemInit(void *arg);
+static void WaitLSNShmemExit(int code, Datum arg);
+static void RegisterWaitLSNShmemExit(void);
const ShmemCallbacks WaitLSNShmemCallbacks = {
.request_fn = WaitLSNShmemRequest,
}
}
+/*
+ * Exit callback to clean up any LSN wait state left behind if this process
+ * exits while waiting. Transaction abort paths call WaitLSNCleanup()
+ * directly.
+ */
+static void
+WaitLSNShmemExit(int code, Datum arg)
+{
+ WaitLSNCleanup();
+}
+
+/*
+ * Register shared-memory exit cleanup once per process. A backend may
+ * execute WAIT FOR LSN more than once.
+ */
+static void
+RegisterWaitLSNShmemExit(void)
+{
+ if (!waitLSNShmemExitRegistered)
+ {
+ on_shmem_exit(WaitLSNShmemExit, 0);
+ waitLSNShmemExitRegistered = true;
+ }
+}
+
/*
* Check if the given LSN type requires recovery to be in progress.
* Standby wait types (replay, write, flush) require recovery;
/* Should have a valid proc number */
Assert(MyProcNumber >= 0 && MyProcNumber < MaxBackends + NUM_AUXILIARY_PROCS);
+ /*
+ * Ensure cleanup is registered before publishing our waiter entry.
+ * on_shmem_exit callbacks run in reverse registration order, so this
+ * callback runs before the earlier-registered ProcKill() and removes the
+ * entry before our PGPROC slot can be reused.
+ */
+ RegisterWaitLSNShmemExit();
+
if (timeout > 0)
{
endtime = TimestampTzPlusMilliseconds(GetCurrentTimestamp(), timeout);
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xlogutils.h"
-#include "access/xlogwait.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
*/
LWLockReleaseAll();
- /*
- * Cleanup waiting for LSN if any.
- */
- WaitLSNCleanup();
-
/* Cancel any pending condition variable sleep, too */
ConditionVariableCancelSleep();