Re: LLVM jit and matview

From: Andres Freund <andres(at)anarazel(dot)de>
To: Dmitry Dolgov <9erthalion6(at)gmail(dot)com>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>, PostgreSQL mailing lists <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: LLVM jit and matview
Date: 2018-07-25 21:47:02
Message-ID: 20180725214702.6v7jxi2zkcv3exar@alap3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs pgsql-hackers

Hi,

On 2018-07-25 08:41:29 -0700, Andres Freund wrote:
> Oh, interesting. It only crashes when compiling LLVM without LLVM's
> asserts enabled, even when using exactly the same LLVM checkout for both
> builds. No idea what that's about, yet.

Oh, well, this took me longer than it should have. The problem, to my
possibly demented mind, is actually kinda funny:

The problematic expression in the query invokes ExecEvalRowNull() (it's
EEOP_WHOLEROW followed by EEOP_NULLTEST_ROWISNOTNULL). With inlining
enabled, that ends up inlining ExecEvalRowNull(), ExecEvalRowNullInt(),
get_cached_rowtype(), ShutdownTupleDescRef() (largely because these are
static functions that'd otherwise prevent ExecEvalRowNull from being
inlined).
get_cached_rowtype() does
/* Need to register shutdown callback to release tupdesc */
RegisterExprContextCallback(econtext,
ShutdownTupleDescRef,
PointerGetDatum(cache_field));
which, in the inlined version, means that ShutdownTupleDescRef is the
inlined copy. So, the query execution sets up a shutdown callback, that
is a JITed function.

But note standard_ExecutorEnd():

/* release JIT context, if allocated */
if (estate->es_jit)
{
jit_release_context(estate->es_jit);
estate->es_jit = NULL;
}

/*
* Must switch out of context before destroying it
*/
MemoryContextSwitchTo(oldcontext);

/*
* Release EState and per-query memory context. This should release
* everything the executor has allocated.
*/
FreeExecutorState(estate);

FreeExecutorState(), which calls the shutdown callbacks, is executed
*after* the JIT context is destroyed! Thereby causing the segfault, as
the shutdown callback now invokes unmapped memory.

The fix is easy, releasing the JIT context should just happen in
FreeExecutorState(). Only thing is that that function has the following
comment in the header:
* Note: this is not responsible for releasing non-memory resources,
* such as open relations or buffer pins. But it will shut down any
* still-active ExprContexts within the EState. That is sufficient
* cleanup for situations where the EState has only been used for expression
* evaluation, and not to run a complete Plan.

I don't really think throwing away functions is a violation of that, but
I think it's possible to argue the other way?

Greetings,

Andres Freund

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Alvaro Herrera 2018-07-25 22:11:13 Re: LLVM jit and matview
Previous Message Benjamin Coutu 2018-07-25 17:45:21 Re: Domain Constraint Violation Error Messages

Browse pgsql-hackers by date

  From Date Subject
Next Message Simon Muller 2018-07-25 22:09:43 Re: Allow COPY's 'text' format to output a header
Previous Message Thomas Munro 2018-07-25 21:37:23 Re: Loaded footgun open_datasync on Windows