Re: ri_Fast* crash w/ nullable UNIQUE constraint

From: Amit Langote <amitlangote09(at)gmail(dot)com>
To: Ayush Tiwari <ayushtiwari(dot)slg01(at)gmail(dot)com>
Cc: Noah Misch <noah(at)leadboat(dot)com>, zhjwpku(at)gmail(dot)com, pgsql-hackers(at)postgresql(dot)org
Subject: Re: ri_Fast* crash w/ nullable UNIQUE constraint
Date: 2026-07-24 10:06:48
Message-ID: CA+HiwqHHK2D69+QqAom+th1kjZGK-0dYnrZujkEGFWpX_ZtxqQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Ayush,

On Tue, Jul 21, 2026 at 7:59 PM Ayush Tiwari
<ayushtiwari(dot)slg01(at)gmail(dot)com> wrote:
> On Tue, 21 Jul 2026 at 11:27, Amit Langote <amitlangote09(at)gmail(dot)com> wrote:
>> I plan to go on vacation starting Sunday for a couple of weeks, so I
>> was hoping to push these patches this week after taking another look.
>> If you or anyone else has comments, please let me know.
>
> Thanks for the patches!
>
> I was reviewing it yesterday and got stalled on 0004, went through
> rest today. 0001 to 0003 looked good to me.

Thanks for the review.

> One thing I got stuck on in 0004 (resettable fn_mcxt): each flush does
> MemoryContextReset(scratch_cxt), but I couldn't find where the cached
> FmgrInfos' fn_extra is cleared. record_eq() (and some cast/eq
> functions) cache state via fn_extra allocated in fn_mcxt, so after the
> reset fn_extra seems to dangle, and the next flush reusing the same
> FmgrInfo reads it back as valid; fmgr_info_copy() zeroes fn_extra for
> what looks like this reason. With a composite key over two batches,
> and an assert after the reset, fn_extra was non-NULL on the second
> batch. Would clearing fn_extra (or re-copying the FmgrInfos) on reset
> make sense, maybe with a record-typed two-batch test?

Good catch. I don't think scratch_cxt should be reset per flush at all
-- fn_extra points into it, so the reset frees state fn_extra still
refers to. Clearing fn_extra too would fix the dangling pointer but
discard the cache every flush, and nothing accumulates during use
anyway: record_eq() allocates only when fn_extra is NULL.

The actual leak is at invalidation, not during use: with fn_mcxt =
TopMemoryContext the cached state outlives fpmeta, so each
repopulation orphans the previous one. v2 keeps the context but never
resets it, deleting it with fpmeta in
InvalidateConstraintCacheCallBack().

I don't think we need a regression test here, since the fix only
prevents a leak.

> Also, the reset is only in ri_FastPathBatchFlush(); ri_FastPathCheck()
> (ALTER TABLE validate / sub-transaction path) uses the same cached
> FmgrInfos and scratch_cxt but doesn't reset. I wonder if the growth this
> patch targets still applies there.

Yes, that applies there too. The problem isn't anything piling up
across flushes, it's that the cached state gets left behind when
fpmeta goes away, so the calling path doesn't come into it at all.

> Doubt: 0005 moves index_beginscan() after the user-id switch in
> ri_FastPathCheck(), but ri_FastPathBatchFlush() still begins the scan
> before the switch. Is that intentional, or worth the same reordering?

Fixed, both sites are consistent now.

Updated patches attached. I don't think much time is left between now
and when I board a plane, so I will commit these when I'm back from
vacation; Aug 5 or 6.

--
Thanks, Amit Langote

Attachment Content-Type Size
v2-0006-Remove-stale-comment-on-ri_FastPathCheck.patch application/octet-stream 1.4 KB
v2-0005-Begin-RI-fast-path-index-scan-under-the-switched-.patch application/octet-stream 3.1 KB
v2-0004-Give-RI-fast-path-cached-FmgrInfos-their-own-memo.patch application/octet-stream 4.2 KB
v2-0002-Fire-fast-path-FK-batches-inside-the-deferred-tri.patch application/octet-stream 8.7 KB
v2-0003-Restrict-RI-fast-path-FK-check-to-btree-reference.patch application/octet-stream 3.3 KB
v2-0001-Handle-nullable-referenced-key-in-RI-fast-path-ch.patch application/octet-stream 7.3 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Shlok Kyal 2026-07-24 10:20:00 Re: Support EXCEPT for ALL SEQUENCES publications
Previous Message Laurenz Albe 2026-07-24 09:51:33 Re: [PATCH] doc: clarify AS requirement when VALUES used in a FROM clause