🌐 AI搜索 & 代理 主页
Skip to content

Commit 7dcea51

Browse files
committed
Avoid unexpected changes of CurrentResourceOwner and CurrentMemoryContext
Users of logical decoding can encounter an unexpected change of CurrentResourceOwner and CurrentMemoryContext. The problem is that, unlike other call sites of RollbackAndReleaseCurrentSubTransaction(), in reorderbuffer.c we fail to restore the original values of these global variables after being clobbered by subtransaction abort. This patch saves the values prior to the call and restores them eventually. In addition, logical.c and logicalfuncs.c had a hack to restore resource owner, presumably because of lack of this restore. Remove that. Instead, because the test coverage here is not very consistent, add an Assert() to ensure that the resowner is kept identical; this would make it easy to detect other cases of bugs were we fail to restore resowner properly. This could be removed later. This is arguably an old bug, but there appears to be no reason to backpatch it and it's risky to do so, so refrain for now. Author: Antonin Houska <ah@cybertec.at> Reported-by: Mihail Nikalayeu <mihailnikalayeu@gmail.com> Reviewed-by: Euler Taveira <euler@eulerto.com> Discussion: https://postgr.es/m/119497.1756892972@localhost
1 parent 20d541a commit 7dcea51

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

src/backend/replication/logical/logical.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,7 @@ LogicalSlotAdvanceAndCheckSnapState(XLogRecPtr moveto,
20822082
bool *found_consistent_snapshot)
20832083
{
20842084
LogicalDecodingContext *ctx;
2085-
ResourceOwner old_resowner = CurrentResourceOwner;
2085+
ResourceOwner old_resowner PG_USED_FOR_ASSERTS_ONLY = CurrentResourceOwner;
20862086
XLogRecPtr retlsn;
20872087

20882088
Assert(moveto != InvalidXLogRecPtr);
@@ -2141,21 +2141,24 @@ LogicalSlotAdvanceAndCheckSnapState(XLogRecPtr moveto,
21412141
* might still have critical updates to do.
21422142
*/
21432143
if (record)
2144+
{
21442145
LogicalDecodingProcessRecord(ctx, ctx->reader);
21452146

2147+
/*
2148+
* We used to have bugs where logical decoding would fail to
2149+
* preserve the resource owner. That's important here, so
2150+
* verify that that doesn't happen anymore. XXX this could be
2151+
* removed once it's been battle-tested.
2152+
*/
2153+
Assert(CurrentResourceOwner == old_resowner);
2154+
}
2155+
21462156
CHECK_FOR_INTERRUPTS();
21472157
}
21482158

21492159
if (found_consistent_snapshot && DecodingContextReady(ctx))
21502160
*found_consistent_snapshot = true;
21512161

2152-
/*
2153-
* Logical decoding could have clobbered CurrentResourceOwner during
2154-
* transaction management, so restore the executor's value. (This is
2155-
* a kluge, but it's not worth cleaning up right now.)
2156-
*/
2157-
CurrentResourceOwner = old_resowner;
2158-
21592162
if (ctx->reader->EndRecPtr != InvalidXLogRecPtr)
21602163
{
21612164
LogicalConfirmReceivedLocation(moveto);

src/backend/replication/logical/logicalfuncs.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
107107
XLogRecPtr end_of_wal;
108108
XLogRecPtr wait_for_wal_lsn;
109109
LogicalDecodingContext *ctx;
110-
ResourceOwner old_resowner = CurrentResourceOwner;
110+
ResourceOwner old_resowner PG_USED_FOR_ASSERTS_ONLY = CurrentResourceOwner;
111111
ArrayType *arr;
112112
Size ndim;
113113
List *options = NIL;
@@ -263,8 +263,18 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
263263
* store the description into our tuplestore.
264264
*/
265265
if (record != NULL)
266+
{
266267
LogicalDecodingProcessRecord(ctx, ctx->reader);
267268

269+
/*
270+
* We used to have bugs where logical decoding would fail to
271+
* preserve the resource owner. Verify that that doesn't
272+
* happen anymore. XXX this could be removed once it's been
273+
* battle-tested.
274+
*/
275+
Assert(CurrentResourceOwner == old_resowner);
276+
}
277+
268278
/* check limits */
269279
if (upto_lsn != InvalidXLogRecPtr &&
270280
upto_lsn <= ctx->reader->EndRecPtr)
@@ -275,13 +285,6 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
275285
CHECK_FOR_INTERRUPTS();
276286
}
277287

278-
/*
279-
* Logical decoding could have clobbered CurrentResourceOwner during
280-
* transaction management, so restore the executor's value. (This is
281-
* a kluge, but it's not worth cleaning up right now.)
282-
*/
283-
CurrentResourceOwner = old_resowner;
284-
285288
/*
286289
* Next time, start where we left off. (Hunting things, the family
287290
* business..)

src/backend/replication/logical/reorderbuffer.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,6 +2215,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
22152215
{
22162216
bool using_subtxn;
22172217
MemoryContext ccxt = CurrentMemoryContext;
2218+
ResourceOwner cowner = CurrentResourceOwner;
22182219
ReorderBufferIterTXNState *volatile iterstate = NULL;
22192220
volatile XLogRecPtr prev_lsn = InvalidXLogRecPtr;
22202221
ReorderBufferChange *volatile specinsert = NULL;
@@ -2692,7 +2693,11 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
26922693
}
26932694

26942695
if (using_subtxn)
2696+
{
26952697
RollbackAndReleaseCurrentSubTransaction();
2698+
MemoryContextSwitchTo(ccxt);
2699+
CurrentResourceOwner = cowner;
2700+
}
26962701

26972702
/*
26982703
* We are here due to one of the four reasons: 1. Decoding an
@@ -2751,7 +2756,11 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
27512756
}
27522757

27532758
if (using_subtxn)
2759+
{
27542760
RollbackAndReleaseCurrentSubTransaction();
2761+
MemoryContextSwitchTo(ccxt);
2762+
CurrentResourceOwner = cowner;
2763+
}
27552764

27562765
/*
27572766
* The error code ERRCODE_TRANSACTION_ROLLBACK indicates a concurrent
@@ -3244,6 +3253,8 @@ ReorderBufferImmediateInvalidation(ReorderBuffer *rb, uint32 ninvalidations,
32443253
SharedInvalidationMessage *invalidations)
32453254
{
32463255
bool use_subtxn = IsTransactionOrTransactionBlock();
3256+
MemoryContext ccxt = CurrentMemoryContext;
3257+
ResourceOwner cowner = CurrentResourceOwner;
32473258
int i;
32483259

32493260
if (use_subtxn)
@@ -3262,7 +3273,11 @@ ReorderBufferImmediateInvalidation(ReorderBuffer *rb, uint32 ninvalidations,
32623273
LocalExecuteInvalidationMessage(&invalidations[i]);
32633274

32643275
if (use_subtxn)
3276+
{
32653277
RollbackAndReleaseCurrentSubTransaction();
3278+
MemoryContextSwitchTo(ccxt);
3279+
CurrentResourceOwner = cowner;
3280+
}
32663281
}
32673282

32683283
/*

0 commit comments

Comments
 (0)