public inbox for [email protected]  
help / color / mirror / Atom feed
From: Amit Kapila <[email protected]>
To: Zhijie Hou (Fujitsu) <[email protected]>
Cc: Xuneng Zhou <[email protected]>
Cc: Fujii Masao <[email protected]>
Cc: Srinath Reddy Sadipiralla <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Subject: Re: Fix race in ReplicationSlotRelease for ephemeral slots
Date: Thu, 11 Jun 2026 16:48:08 +0530
Message-ID: <CAA4eK1LkRdbm5XA=qa82Rp_y4rnyJh8pypMWVqOezOZpzy=Oaw@mail.gmail.com> (raw)
In-Reply-To: <CAA4eK1LqFBKCkX2eoX3iQPxJJnzWTaCpdh9zNotxuoG8BgjdtA@mail.gmail.com>
References: <TY4PR01MB177184FF9EE916F577E1F554194082@TY4PR01MB17718.jpnprd01.prod.outlook.com>
	<CAFC+b6o-hD5VxVLZQovmHSYykF8Qzq3eiuBU-U1F_yR9-y6P_w@mail.gmail.com>
	<TY4PR01MB177180A7CE60BCDF286B1C6F594172@TY4PR01MB17718.jpnprd01.prod.outlook.com>
	<CABPTF7VyH1-W2xnDspECDEzFGQj=WTFpZBCqKfM11OAZa6gQHQ@mail.gmail.com>
	<CAHGQGwE+2WSqiAYgNJRkf_twdB+uRGozjjGhUn76vUKZ8dzbSA@mail.gmail.com>
	<CABPTF7VeA8szPv7LYDVY9_7LftV-HM8NFVQR2natPKmr73JW+A@mail.gmail.com>
	<TY4PR01MB1771887D33612C5A45F7E9CDF941E2@TY4PR01MB17718.jpnprd01.prod.outlook.com>
	<CAA4eK1LqFBKCkX2eoX3iQPxJJnzWTaCpdh9zNotxuoG8BgjdtA@mail.gmail.com>

On Thu, Jun 11, 2026 at 2:52 PM Amit Kapila <[email protected]> wrote:
>
> On Sat, Jun 6, 2026 at 3:05 PM Zhijie Hou (Fujitsu)
> <[email protected]> wrote:
> >
> > On Friday, June 5, 2026 8:45 PM Xuneng Zhou <[email protected]> wrote:
> > > On Wed, Jun 3, 2026 at 8:03 PM Fujii Masao <[email protected]> wrote:
> > > >
> > > > On Tue, Jun 2, 2026 at 3:00 PM Xuneng Zhou <[email protected]>
> > > wrote:
> > > >
> > > >   /* Drop the local slot if it is not required to be retained. */
> > > >   if (!local_sync_slot_required(local_slot, remote_slot_list))
> > > >   {
> > > > + bool dropped = false;
> > > > + NameData slot_name = {0};
> > > > + Oid slot_database = local_slot->data.database;
> > > >   bool synced_slot;
> > > >
> > > > Is it really safe to read slot_database before acquiring the database lock?
> > >
> > > Reading slot_database before taking the database lock seems not
> > > inherently unsafe by itself. The comment suggests that the lock is
> > > primarily used to prevent conflicts with the startup process running
> > > ReplicationSlotsDropDBSlots() during db-drop replay; it does not
> > > protect replication slot array reuse.
> > >
> > > The unsafe part could be reading slot_database from local_slot after
> > > ReplicationSlotControlLock has been released. At this point, the slot
> > > array cell may already have been freed and reused, so the value read
> > > may no longer belong to the slot that get_local_synced_slots()
> > > originally collected. As a result, we could end up locking the wrong
> > > database.
> > >
> > > There seems to be two related issues:
> > >
> > > 1) Before drop: reading local_slot->data.database /
> > > local_slot->data.name after the slot-array lock was released, before
> > > verifying the cell still represents the same synced slot.
> >
> > I recall condition (1) is considered acceptable, since the database lock is
> > released immediately after re-verifying that the slot is no longer the original
> > 'synced' one anyway. Additionally, this race can only occur when replaying a
> > DROP DATABASE, which is rare in practice. Since we only take a shared lock, it
> > does not seem to cause real issues.
> >
>
> It seems that (1) is talking about the access to local_slot->data.name
> before we acquire database lock in local_sync_slot_required() whereas
> your response doesn't seem to address that concern. If not, then how
> exactly does the database lock protect what we are doing in
> local_sync_slot_required()?
>

I re-analyzed this case and found the 'Before-drop' case is safe. In
the gap between get_local_synced_slots() releasing
ReplicationSlotControlLock and LockSharedObject,
ReplicationSlotsDropDBSlots() can run and free a synced slot cell
because the slotsync worker holds no database lock yet. The cell can
then be reused by any user-created (non-synced) slot. It could lead to
following risks which I think are already addressed due to recheck of
sync flag.

1. Stale name read in local_sync_slot_required(): The reused cell
holds a different name. local_sync_slot_required() might return false
(drop needed). But then the in_use && synced spinlock check sees
synced = false and skips the actual drop. The wrong decision is
caught.
2. Wrong database OID read at line 551: The reused cell holds OID_B
from the new slot. We lock OID_B, then at lines 563–565 we see synced
= false, skip the drop, and unlock OID_B at line 579. Since no drop
occurred, the cell is still the same non-synced slot, so the lock and
unlock see the same OID_B. Symmetric — no lock leak.
3. Acquiring the wrong slot at line 575: Once the shared database lock
is held at line 551, ReplicationSlotsDropDBSlots() is blocked from
freeing the cell. The slotsync worker itself won't free a synced slot
from any other code path while inside this function. So, this should
not happen.

Does this match your analysis? If so, After-drop case is still a risk,
and for that, the patch proposed in email [1] seems to address it.

[1] - https://www.postgresql.org/message-id/CABPTF7VyH1-W2xnDspECDEzFGQj%3DWTFpZBCqKfM11OAZa6gQHQ%40mail.g...

-- 
With Regards,
Amit Kapila.





view thread (27+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: Fix race in ReplicationSlotRelease for ephemeral slots
  In-Reply-To: <CAA4eK1LkRdbm5XA=qa82Rp_y4rnyJh8pypMWVqOezOZpzy=Oaw@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

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