| From: | Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com> |
|---|---|
| To: | Andrey Borodin <x4mmm(at)yandex-team(dot)ru> |
| Cc: | Bryan Green <dbryan(dot)green(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | Re: [PATCH]Fix pg_xact corruption from subtransaction abort after subcommit |
| Date: | 2026-08-09 22:38:46 |
| Message-ID: | CAB8bMivHtNJXKJBhZwsGXOCQ6wxo9cxTa7DxkwsHsG0wwfnv_Q@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi, Andrey!
On whether a catchable ERROR can happen after AtSubCommit_childXids()
without an extension callback: yes. Allocations inside stock
AtSubCommit_Notify() are enough to raise one. That reaches Bryan's
steps (A) and (B) below. It does not by itself give a neat clog TRAP on
the later parent COMMIT. Under this OOM setup that COMMIT usually dies
in SIGSEGV first. The childXids / pg_xact split is already present
before COMMIT, which is the corruption window Bryan described.
Bryan's sequence is:
(A) AtSubCommit_childXids() publishes the subxid into parent->childXids.
(B) A later catchable ERROR aborts the subxact and marks that XID aborted
in pg_xact, without removing it from parent->childXids.
(C) Parent COMMIT then calls TransactionIdSetTreeStatus() / CommitTree
over that mixed list (assert TRAP, or silent clog corruption).
(A)+(B) are visible under gdb with no extension. For a clean (C) with
the clog assert, an extension COMMIT_SUB callback that raises ERROR
still works as Bryan sketched.
Setup in short: parent and subxact both queue NOTIFYs, then force
memory pressure so the pending-notify merge in AtSubCommit_Notify()
hits a catchable out-of-memory ERROR; PL/pgSQL EXCEPTION WHEN OTHERS
swallows it.
Observed under gdb:
1) (A) Subxid published into the parent list, still before Notify merge:
>>> AtSubCommit_childXids ENTER xid=696 parent->nChildXids=0
>>> after AtSubCommit_childXids: parent->nChildXids=1 childXids[0]=696
>>> AtSubCommit_Notify ENTER parent->nChildXids=1 childXids[0]=696
2) Catchable OOM later in the same CommitSubTransaction():
#0 MemoryContextAllocationFailure (...) at mcxt.c:1203
#6 AddEventToPendingNotifies (...) at async.c:3228
#7 AtSubCommit_Notify () at async.c:2498
#8 CommitSubTransaction () at xact.c:5207
#9 ReleaseCurrentSubTransaction () at xact.c:4837
#10 exec_stmt_block (...) at pl_exec.c:1859
...
3) (B) Abort marks the same XID aborted in pg_xact while it remains in
parent->childXids (AbortSubTransaction -> RecordTransactionAbort ->
TransactionIdAbortTree; AtSubAbort_childXids only frees *this* subxact's
own child list, not the parent's entry):
>>> TransactionIdAbortTree xid=696 nchildren=0
==== BUG STATE after CleanupSubTransaction ====
parent->nChildXids = 1
parent->childXids[0] = 696 DidAbort=1 DidCommit=0
==== end BUG STATE ====
вс, 9 авг. 2026 г. в 22:57, Andrey Borodin <x4mmm(at)yandex-team(dot)ru>:
> Hi Bryan,
>
> Thank you for finding this.
>
> > On 9 Aug 2026, at 08:39, Bryan Green <dbryan(dot)green(at)gmail(dot)com> wrote:
> >
> > path can corrupt pg_xact
>
> That's a very interesting corruption case. We observed something very much
> like
> this with "failed to find parent tuple for heap-only tuple".
>
> But so far I can't build a test with an error between
>
> AtSubCommit_childXids();
> and
> PopTransaction();
>
> I meant, yeah, extensions can do this, but that's a weak argument. Maybe
> some
> allocations inside AtSubCommit_Notify() can cause catachable error... IDK.
>
> This actually looks like a corruption that bite us. But how an error can
> happen
> in this path? If it's an extension, which extension is thorwin it? In-tree
> extensions seems to avoid erroring out in callbacks. Maybe something in
> AtEOXact_GUC()?
>
>
> Best regards, Andrey Borodin.
>
>
--
Regards,
Rachitskiy Andrey
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Tom Lane | 2026-08-09 23:53:57 | Re: [PATCH] Fix vacuum_delay_point happening inside lock |
| Previous Message | Kevin Rocker | 2026-08-09 22:36:37 | Re: [PATCH] Fix vacuum_delay_point happening inside lock |