postgres.git / summary / log / commit / refs

commit    c7256e6564fa580ecaad97b6a68e57652d4b09d4
Author:   Amit Kapila <akapila@postgresql.org>
Date:     Tue Sep 12 04:53:17 2023 +0000
First released in: 11.22, 12.17, 13.13, 14.10, 15.5

    Fix uninitialized access to InitialRunningXacts during decoding after ERROR.
    
    The transactions and subtransactions array that was allocated under
    snapshot builder memory context and recorded during decoding was not
    cleared in case of errors. This can result in an assertion failure if we
    attempt to retry logical decoding within the same session. To address this
    issue, we register a callback function under the snapshot builder memory
    context to clear the recorded transactions and subtransactions array along
    with the context.
    
    This problem doesn't exist in PG16 and HEAD as instead of using
    InitialRunningXacts, we added the list of transaction IDs and
    sub-transaction IDs, that have modified catalogs and are running during
    snapshot serialization, to the serialized snapshot (see commit 7f13ac8123).
    
    Author: Hou Zhijie
    Reviewed-by: Amit Kapila
    Backpatch-through: 11
    Discussion: http://postgr.es/m/18055-ab3beed9f4b7b7d6@postgresql.org


src/backend/replication/logical/snapbuild.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 4c951678c0a..3eaaaac6b3a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -300,6 +300,17 @@ static void SnapBuildWaitSnapshot(xl_running_xacts *running, TransactionId cutof static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn); static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn); +/* + * Memory context reset callback for clearing the array of running transactions + * and subtransactions. + */ +static void +SnapBuildResetRunningXactsCallback(void *arg) +{ + NInitialRunningXacts = 0; + InitialRunningXacts = NULL; +} + /* * Allocate a new snapshot builder. * @@ -316,6 +327,7 @@ AllocateSnapshotBuilder(ReorderBuffer *reorder, MemoryContext context; MemoryContext oldcontext; SnapBuild *builder; + MemoryContextCallback *mcallback; /* allocate memory in own context, to have better accountability */ context = AllocSetContextCreate(CurrentMemoryContext, @@ -341,6 +353,10 @@ AllocateSnapshotBuilder(ReorderBuffer *reorder, builder->building_full_snapshot = need_full_snapshot; builder->two_phase_at = two_phase_at; + mcallback = palloc0(sizeof(MemoryContextCallback)); + mcallback->func = SnapBuildResetRunningXactsCallback; + MemoryContextRegisterResetCallback(CurrentMemoryContext, mcallback); + MemoryContextSwitchTo(oldcontext); /* The initial running transactions array must be empty. */ @@ -366,10 +382,6 @@ FreeSnapshotBuilder(SnapBuild *builder) /* other resources are deallocated via memory context reset */ MemoryContextDelete(context); - - /* InitialRunningXacts is freed along with the context */ - NInitialRunningXacts = 0; - InitialRunningXacts = NULL; } /* [parent: ad6508c104f7]