From aa65f12b4938e73dd86049bbd979e9c3ec334088 Mon Sep 17 00:00:00 2001 From: Shihao Date: Wed, 23 Sep 2026 08:05:20 -0400 Subject: [PATCH v9 2/3] Check the PID when reading the transaction status of a backend pgstat_read_current_status() copies the status entry of a backend, then reads its transaction status from its PGPROC entry, in a second step. If the backend exited and its proc number was reused in between, the transaction ID, xmin and subtransaction counters of the new backend were reported under the PID and the session user of the old one. Pass the PID copied from the status entry to ProcNumberGetTransactionIds(), and report nothing if the PGPROC entry does not hold it anymore, checked under ProcArrayLock. Reported-by: Bertrand Drouvot Author: Shihao Zhong Discussion: https://postgr.es/m/arN+VT3xyiTY/iUD@bdtpg --- src/backend/storage/ipc/procarray.c | 8 ++++++-- src/backend/utils/activity/backend_status.c | 1 + src/include/storage/procarray.h | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index b7e03134ed8..7124974332d 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -3120,9 +3120,13 @@ ProcNumberGetProc(ProcNumber procNumber) * Get the xid, xmin, nsubxid and overflow status of the backend. The * result may be out of date arbitrarily quickly, so the caller must be * careful about how this information is used. + * + * "pid" is the PID of the backend the caller expects to find using this + * proc number. If the proc number has been reused by a different backend + * since the caller looked at it, nothing is reported. */ void -ProcNumberGetTransactionIds(ProcNumber procNumber, TransactionId *xid, +ProcNumberGetTransactionIds(ProcNumber procNumber, int pid, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed) { PGPROC *proc; @@ -3139,7 +3143,7 @@ ProcNumberGetTransactionIds(ProcNumber procNumber, TransactionId *xid, /* Need to lock out additions/removals of backends */ LWLockAcquire(ProcArrayLock, LW_SHARED); - if (proc->pid != 0) + if (proc->pid != 0 && proc->pid == pid) { *xid = proc->xid; *xmin = proc->xmin; diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c index d685fc5cd87..eb78ca8795b 100644 --- a/src/backend/utils/activity/backend_status.c +++ b/src/backend/utils/activity/backend_status.c @@ -912,6 +912,7 @@ pgstat_read_current_status(void) */ localentry->proc_number = procNumber; ProcNumberGetTransactionIds(procNumber, + localentry->backendStatus.st_procpid, &localentry->backend_xid, &localentry->backend_xmin, &localentry->backend_subxact_count, diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index d718a5b542f..b41514178ad 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -62,7 +62,7 @@ extern bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type); extern PGPROC *ProcNumberGetProc(int procNumber); -extern void ProcNumberGetTransactionIds(int procNumber, TransactionId *xid, +extern void ProcNumberGetTransactionIds(int procNumber, int pid, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed); extern PGPROC *BackendPidGetProc(int pid); -- 2.37.1 (Apple Git-137.1)