[PATCH] Release a replication slot leaked by a caught subtransaction error

Started by Bryan Green16 days ago3 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253355
psql -h localhost -U postgres

Built from patchset v1 (message #1), August 24, 2026 at 01:48 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253355_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253355_1 && git checkout t253355_1

Patchset v1 (message #1) is on t253355_1

Jump to latest
#1Bryan Green
dbryan.green@gmail.com

Greetings,

A SQL slot function that errors after acquiring MyReplicationSlot leaks the
slot when the error is caught by a PL/pgSQL EXCEPTION handler: the
subtransaction aborts without releasing it, MyReplicationSlot stays set, and
the next slot operation in the session trips Assert(!MyReplicationSlot).

Releasing on error is done at the top level, in PostgresMain(), and the
comment there is explicit that AbortTransaction() must not do it:

    /*
     * We can't release replication slots inside AbortTransaction() as we
     * need to be able to start and abort transactions while having a slot
     * acquired. ...
     */

A caught error never reaches that top-level path, so the slot is never let
go.

Reproduction --

    DO $$
    BEGIN
        PERFORM pg_create_physical_replication_slot('s', false);
        BEGIN
            PERFORM pg_replication_slot_advance('s', '0/1');
        EXCEPTION WHEN object_not_in_prerequisite_state THEN
            NULL;
        END;
        PERFORM pg_create_physical_replication_slot('s2');
    END $$;

    TRAP: failed Assert("!MyReplicationSlot"), slotfuncs.c:51

The fix releases the slot in AbortSubTransaction(), but only when it was
acquired at or below the aborting subtransaction, tracked by a new
MyReplicationSlotSubid.  That preserves the property the comment above
depends on: a slot acquired outside the current subtransaction survives its
abort, which is what logical apply workers and REPACK rely on.

The patch adds a TAP test for the two paths that actually leak: the acquire
path (pg_replication_slot_advance) and the create path
(pg_create_logical_replication_slot with a missing plugin, which errors
after the slot is acquired).  The test fails without the fix and passes with
it; the regression suite passes.

--
Bryan Green
EDB: https://www.enterprisedb.com

Attachments:

t253355_1
0001-Release-a-replication-slot-leaked-by-a-caught-subtra.patchtext/plain; charset=UTF-8; name=0001-Release-a-replication-slot-leaked-by-a-caught-subtra.patchDownload+76-1
#2Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Bryan Green (#1)
Re: [PATCH] Release a replication slot leaked by a caught subtransaction error

Hi,

On Sat, Aug 8, 2026 at 8:33 PM Bryan Green <dbryan.green@gmail.com> wrote:

A SQL slot function that errors after acquiring MyReplicationSlot leaks the
slot when the error is caught by a PL/pgSQL EXCEPTION handler: the
subtransaction aborts without releasing it, MyReplicationSlot stays set, and
the next slot operation in the session trips Assert(!MyReplicationSlot).

Releasing on error is done at the top level, in PostgresMain(), and the
comment there is explicit that AbortTransaction() must not do it:

Thanks. This issue is being discussed in this thread:
/messages/by-id/CALj2ACU-mVxrak_Q0EP1sZg8h=7pg1d09Gj6Ody5jH6zxiZQLA@mail.gmail.com.

--
Bharath Rupireddy
Amazon Web Services: https://aws.amazon.com

#3Bryan Green
dbryan.green@gmail.com
In reply to: Bharath Rupireddy (#2)
Re: [PATCH] Release a replication slot leaked by a caught subtransaction error

On 8/8/26 22:46, Bharath Rupireddy wrote:

Hi,

On Sat, Aug 8, 2026 at 8:33 PM Bryan Green <dbryan.green@gmail.com> wrote:

A SQL slot function that errors after acquiring MyReplicationSlot leaks the
slot when the error is caught by a PL/pgSQL EXCEPTION handler: the
subtransaction aborts without releasing it, MyReplicationSlot stays set, and
the next slot operation in the session trips Assert(!MyReplicationSlot).

Releasing on error is done at the top level, in PostgresMain(), and the
comment there is explicit that AbortTransaction() must not do it:

Thanks. This issue is being discussed in this thread:
/messages/by-id/CALj2ACU-mVxrak_Q0EP1sZg8h=7pg1d09Gj6Ody5jH6zxiZQLA@mail.gmail.com.

Apologies for missing this. I will catch up on this thread! Thanks for
bringing it to my attention!

--
Bryan Green
EDB: https://www.enterprisedb.com