Re: GetBufferDescriptor() being called for local buffers from MarkBufferDirtyHint()
Ayush Tiwari <ayushtiwari.slg01@gmail.com>
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
To: Michael Paquier <michael@paquier.xyz>
Cc: Andres Freund <andres@anarazel.de>,
Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>, PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Date: 2026-06-30T19:17:46Z
Lists: pgsql-hackers
Hi,
On Mon, 29 Jun 2026 at 13:29, Ayush Tiwari <ayushtiwari.slg01@gmail.com>
wrote:
>
> Given the discussion here, I tried making the buffer descriptor accessors
> take
> a signed index and adding range assertions.
>
> Most callers already pass signed buffer indexes derived from Buffer values
> (e.g. buffer - 1, or -buffer - 1 for local buffers). The only caller I
> found
> that passes an unsigned value to GetBufferDescriptor() is
> ClockSweepTick(), and
> that normalizes the value before returning it, so it should still be less
> than
> NBuffers.
>
> The change looked fairly straightforward to me, unless I'm missing
> something.
> I also made the same change for GetLocalBufferDescriptor(), since it has
> the
> same uint32 signature and takes local buffer indexes.
>
cfbot flagged v1 in an assertion-enabled (cassert) build: anything that
uses a
temporary table hits the new assertion in GetLocalBufferDescriptor():
TRAP: failed Assert("id >= 0 && id < NLocBuffer"), buf_internals.h
GetLocalBufferDescriptor
InitLocalBuffers
ExtendBufferedRelLocal -> ... -> heap_insert
It looks like InitLocalBuffers() initializes the descriptors in a loop
before
it sets NLocBuffer, so during that loop the assert sees NLocBuffer == 0.
The
access itself seems fine, since the array is already allocated with
num_temp_buffers entries; it's just that this is the one place that runs
before the bound the assert checks against is set. (The shared path doesn't
run into this, since NBuffers is already set when BufferManagerShmemInit()
does the equivalent loop.)
I'm not sure which way would be preferable here if are adding assert for
LocalBufferDescriptor too:
1. set NLocBuffer = nbufs before the init loop, so the loop can keep using
GetLocalBufferDescriptor(); or
2. leave NLocBuffer where it is and index LocalBufferDescriptors[]
directly
in that loop.
Regards,
Ayush
Commits
-
Switch Get[Local]BufferDescriptor() to use a signed value in input
- ba4134075a82 master landed
-
Fix MarkBufferDirtyHint() to not call GetBufferDescriptor() for local buffers
- e18b0cb7344c 19 (unreleased) landed
-
Require share-exclusive lock to set hint bits and to flush
- 82467f627bd4 19 (unreleased) cited