diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index de89be8d75..b0eb267971 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -4563,6 +4563,7 @@ set_indexsafe_procflags(void) LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->statusFlags |= PROC_IN_SAFE_IC; + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags; LWLockRelease(ProcArrayLock); } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index e63c86cae4..8b79c6b6fd 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1991,6 +1991,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, MyProc->statusFlags |= PROC_IN_VACUUM; if (params->is_wraparound) MyProc->statusFlags |= PROC_VACUUM_FOR_WRAPAROUND; + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags; LWLockRelease(ProcArrayLock); } diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c index 51ffb623c0..34b3bdd61c 100644 --- a/src/backend/replication/logical/logical.c +++ b/src/backend/replication/logical/logical.c @@ -195,6 +195,7 @@ StartupDecodingContext(List *output_plugin_options, { LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->statusFlags |= PROC_IN_LOGICAL_DECODING; + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags; LWLockRelease(ProcArrayLock); } diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 91ca397857..73c8ec7f62 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -696,6 +696,7 @@ ReplicationSlotRelease(void) /* might not have been set when we've been a plain slot */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->statusFlags &= ~PROC_IN_LOGICAL_DECODING; + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags; LWLockRelease(ProcArrayLock); diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index bc40c454de..cfb2fd6cd4 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -308,6 +308,7 @@ InitWalSender(void) Assert(MyProc->xmin == InvalidTransactionId); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); MyProc->statusFlags |= PROC_AFFECTS_ALL_HORIZONS; + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags; LWLockRelease(ProcArrayLock); } diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index b3cd248fb6..b8201418ed 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -608,6 +608,7 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid) Assert(ProcGlobal->subxidStates[myoff].overflowed == false); ProcGlobal->statusFlags[myoff] = 0; + proc->pgxactoff = InvalidPGXactOff; /* Keep the PGPROC array sorted. See notes above */ movecount = arrayP->numProcs - myoff - 1; @@ -715,6 +716,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid) Assert(!LWLockHeldByMe(ProcArrayLock)); LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); Assert(proc->statusFlags == ProcGlobal->statusFlags[proc->pgxactoff]); + Assert(PGXactOffIsValid(MyProc->pgxactoff)); proc->statusFlags &= ~PROC_VACUUM_STATE_MASK; ProcGlobal->statusFlags[proc->pgxactoff] = proc->statusFlags; LWLockRelease(ProcArrayLock); @@ -755,6 +757,7 @@ ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid) if (proc->statusFlags & PROC_VACUUM_STATE_MASK) { proc->statusFlags &= ~PROC_VACUUM_STATE_MASK; + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[proc->pgxactoff] = proc->statusFlags; } @@ -2636,6 +2639,7 @@ ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc) MyProc->xmin = TransactionXmin = xmin; MyProc->statusFlags = (MyProc->statusFlags & ~PROC_XMIN_FLAGS) | (proc->statusFlags & PROC_XMIN_FLAGS); + Assert(PGXactOffIsValid(MyProc->pgxactoff)); ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags; result = true; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 162b1f919d..1941618aa3 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -192,6 +192,10 @@ InitProcGlobal(void) procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC)); MemSet(procs, 0, TotalProcs * sizeof(PGPROC)); ProcGlobal->allProcs = procs; + for (int index = 0; index < TotalProcs; index++) + { + procs[index].pgxactoff = InvalidPGXactOff; + } /* XXX allProcCount isn't really all of them; it excludes prepared xacts */ ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS; diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 18891a86fb..72ca279f78 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -127,6 +127,12 @@ typedef enum PROC_WAIT_STATUS_ERROR, } ProcWaitStatus; +/* + * Invalid value for PGPROC->pgxactoff. + */ +#define InvalidPGXactOff -1 +#define PGXactOffIsValid(pgxactoff) ((pgxactoff) != InvalidPGXactOff) + /* * Each backend has a PGPROC struct in shared memory. There is also a list of * currently-unused PGPROC structs that will be reallocated to new backends.