agora inbox for pgsql-committers@postgresql.org  
help / color / mirror / Atom feed
pgsql: bufmgr: Fix race in LockBufferForCleanup()
2+ messages / 1 participants
[nested] [flat]

* pgsql: bufmgr: Fix race in LockBufferForCleanup()
@ 2026-06-30 01:37  Fujii Masao <fujii@postgresql.org>
  0 siblings, 0 replies; 2+ messages in thread

From: Fujii Masao @ 2026-06-30 01:37 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

bufmgr: Fix race in LockBufferForCleanup()

LockBufferForCleanup() acquires the exclusive content lock, checks the
buffer's shared pin count, and, if other pins remain, registers itself
as the BM_PIN_COUNT_WAITER before waiting for an unpin notification.

Since commits 5310fac6e0f and c75ebc657ffc, however, a shared buffer
pin can be released while BM_LOCKED is set, introducing the following
race:

- LockBufferForCleanup() observes a refcount greater than one.
- Before it sets BM_PIN_COUNT_WAITER, another backend releases the
  last conflicting pin.
- Since BM_PIN_COUNT_WAITER is not yet set, no wakeup is sent.
- LockBufferForCleanup() then sets BM_PIN_COUNT_WAITER and goes to
  sleep, even though only its own pin remains.

As a result, LockBufferForCleanup() can sleep indefinitely because
the wakeup corresponding to the last conflicting unpin has already been
missed.

Fix this by setting BM_PIN_COUNT_WAITER while holding the buffer
header lock, then rechecking the refcount before releasing the content
lock. If only our pin remains, clear the waiter state and proceed
without sleeping. Otherwise, wait as before.

This issue was reported by buildfarm member skink, where it manifested
as intermittent timeouts in 048_vacuum_horizon_floor.pl.

Backpatch to v19, where commits 5310fac6e0f and c75ebc657ffc
introduced the race.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/7685519a-0bf9-4e17-93ca-7e3aa10fa29c@gmail.com
Backpatch-through: 19

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/8d85cb889a395f08d58e59c31a67f199f0fc25c3

Modified Files
--------------
src/backend/storage/buffer/bufmgr.c | 68 +++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 21 deletions(-)



^ permalink  raw  reply  [nested|flat] 2+ messages in thread

* pgsql: bufmgr: Fix race in LockBufferForCleanup()
@ 2026-06-30 01:38  Fujii Masao <fujii@postgresql.org>
  0 siblings, 0 replies; 2+ messages in thread

From: Fujii Masao @ 2026-06-30 01:38 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

bufmgr: Fix race in LockBufferForCleanup()

LockBufferForCleanup() acquires the exclusive content lock, checks the
buffer's shared pin count, and, if other pins remain, registers itself
as the BM_PIN_COUNT_WAITER before waiting for an unpin notification.

Since commits 5310fac6e0f and c75ebc657ffc, however, a shared buffer
pin can be released while BM_LOCKED is set, introducing the following
race:

- LockBufferForCleanup() observes a refcount greater than one.
- Before it sets BM_PIN_COUNT_WAITER, another backend releases the
  last conflicting pin.
- Since BM_PIN_COUNT_WAITER is not yet set, no wakeup is sent.
- LockBufferForCleanup() then sets BM_PIN_COUNT_WAITER and goes to
  sleep, even though only its own pin remains.

As a result, LockBufferForCleanup() can sleep indefinitely because
the wakeup corresponding to the last conflicting unpin has already been
missed.

Fix this by setting BM_PIN_COUNT_WAITER while holding the buffer
header lock, then rechecking the refcount before releasing the content
lock. If only our pin remains, clear the waiter state and proceed
without sleeping. Otherwise, wait as before.

This issue was reported by buildfarm member skink, where it manifested
as intermittent timeouts in 048_vacuum_horizon_floor.pl.

Backpatch to v19, where commits 5310fac6e0f and c75ebc657ffc
introduced the race.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Xuneng Zhou <xunengzhou@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/7685519a-0bf9-4e17-93ca-7e3aa10fa29c@gmail.com
Backpatch-through: 19

Branch
------
REL_19_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/74e93d0f0000f197f27d311ab5fd70b3adfbac26

Modified Files
--------------
src/backend/storage/buffer/bufmgr.c | 68 +++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 21 deletions(-)



^ permalink  raw  reply  [nested|flat] 2+ messages in thread


end of thread, other threads:[~2026-06-30 01:38 UTC | newest]

Thread overview: 2+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-06-30 01:37 pgsql: bufmgr: Fix race in LockBufferForCleanup() Fujii Masao <fujii@postgresql.org>
2026-06-30 01:38 pgsql: bufmgr: Fix race in LockBufferForCleanup() Fujii Masao <fujii@postgresql.org>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox