Re: Pg18 Recursive Crash

From: David Rowley <dgrowleyml(at)gmail(dot)com>
To: Nathan Bossart <nathandbossart(at)gmail(dot)com>
Cc: Paul Ramsey <pramsey(at)cleverelephant(dot)ca>, PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Pg18 Recursive Crash
Date: 2024-12-17 21:58:37
Message-ID: CAApHDvo11HBcb624eTAkXMBkN3=fji_DP+BqNYGYfNNo8nOxaQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, 17 Dec 2024 at 07:10, Nathan Bossart <nathandbossart(at)gmail(dot)com> wrote:
> git-bisect is pointing me to https://postgr.es/c/0f57382. Here is the
> trace I'm seeing:
>
> TRAP: failed Assert("op->d.fetch.kind == slot->tts_ops"), File: "../postgresql/src/backend/executor/execExprInterp.c", Line: 2244, PID: 5031
> 0 postgres 0x000000010112d068 ExceptionalCondition + 108
> 1 postgres 0x0000000100e54f04 ExecInterpExpr + 604
> 2 postgres 0x0000000100e5bd50 LookupTupleHashEntry + 116
> 3 postgres 0x0000000100e8e580 ExecRecursiveUnion + 140

This is caused by me being overly optimistic about getting rid of the
slot deformation step in the ExprState evaluation for hashing. I
must've not fully understood the method of how hash table lookups are
performed for grouping requirements and mistakenly thought it was ok
to use &TTSOpsMinimalTuple for hashing the same as the equality code
is doing in ExecBuildGroupingEqual(). It turns out the ExprState built
by ExecBuildGroupingEqual() always uses slots with minimal tuples due
to how LookupTupleHashEntry_internal() always creates a hash table
entry without a key and then does ExecCopySlotMinimalTuple() to put
the tuple into the hash table after the hash bucket is reserved.
That's not the case for generating the hash value as that uses
whichever slot is passed to LookupTupleHashEntry().

To fix the reported crash, I propose adding a new parameter to
BuildTupleHashTableExt() to allow passing of the TupleTableSlotOps.
Really, I could just set scratch.d.fetch.kind to NULL in
ExecBuildHash32FromAttrs() so that the hashing ExprState is always
built with a deform step, but there are many cases (e.g notSubplan.c)
where a virtual slot is always used, so it would be nice to have some
way to pass the TupleTableSlotOps in for cases where it's known so
that the deform step can be eliminated when it's not needed.

The slightly annoying thing here is that the attached patch passes the
TupleTableSlotOps as NULL in nodeSetOp.c. Per nodeAppend.c line 186,
Append does not go to much effort to setting a fixed
TupleTableSlotOps. Really it could loop over all the child plans and
check if those have fixed slot types of the same type and then fix its
own resulting slot. For nodeSetOps.c use case, since the planner
(currently) injects the flag into the target list, it'll always
project and use a virtual slot type. It's maybe worth coming back and
adjusting nodeAppend.c so it works a bit harder to fix its slot type.
I think that's likely for another patch, however. Tom is also
currently working on nodeSetOps.c to change how all this works so it
no longer uses the flags method to determine the outer and inner
sides.

I plan to push the attached patch soon.

David

Attachment Content-Type Size
v1-0001-Fix-incorrect-slot-type-in-BuildTupleHashTableExt.patch application/octet-stream 8.6 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2024-12-17 22:04:49 Re: Pg18 Recursive Crash
Previous Message Andres Freund 2024-12-17 21:47:31 Re: Crash: invalid DSA memory alloc request