segfault with expression index, btree_gist and HOT Update

From: Tobias Bussmann <t(dot)bussmann(at)gmx(dot)net>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: Jürg Senn <juerg(dot)senn(at)scnat(dot)ch>
Subject: segfault with expression index, btree_gist and HOT Update
Date: 2018-11-07 14:46:46
Message-ID: 77EC85F8-B515-4CD3-B68E-26D82CF48D58@gmx.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hello,

my colleague Jürg Senn recently found a backend crash in Postgres 11 and trimmed it down to a reproducible test case. Testing revealed the crash is still present in last week's master branch but not in 10. I further simplified the test case to:

CREATE EXTENSION btree_gist;
CREATE TABLE segfault (i int);
CREATE INDEX ON segfault USING gist ((i + 10));
INSERT INTO segfault VALUES (1);
UPDATE segfault SET i = 2;

Our tests were performed on macOS: PostgreSQL 12devel on x86_64-apple-darwin17.7.0, compiled by Apple LLVM version 9.1.0 (clang-902.0.39.2), 64-bit

Apparently the segfault happens within the check for the possibility of HOT Updates with expression / functional indexes which was added by c203d6cf8 in 11.

The backtrace on the segfault is:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xb)
* frame #0: 0x00007fff51b06cc0 libsystem_platform.dylib`_platform_memcmp + 288
frame #1: 0x0000000108b8b7e3 postgres`datumIsEqual(value1=11, value2=12, typByVal=false, typLen=8) at datum.c:249
frame #2: 0x000000010869ca52 postgres`ProjIndexIsUnchanged(relation=0x000000010b292778, oldtup=0x00007ffee75e28b8, newtup=0x00007f9f84007e70) at heapam.c:4551
frame #3: 0x000000010869b60f postgres`heap_update(relation=0x000000010b292778, otid=0x00007ffee75e2bc8, newtup=0x00007f9f84007e70, cid=0, crosscheck=0x0000000000000000, wait=true, hufd=0x00007ffee75e2a98, lockmode=0x00007ffee75e2a80) at heapam.c:4242
frame #4: 0x000000010892c381 postgres`ExecUpdate(mtstate=0x00007f9f840066c0, tupleid=0x00007ffee75e2bc8, oldtuple=0x0000000000000000, slot=0x00007f9f84007708, planSlot=0x00007f9f84006bd8, epqstate=0x00007f9f84006780, estate=0x00007f9f84006318, canSetTag=true) at nodeModifyTable.c:1208
frame #5: 0x000000010892a57e postgres`ExecModifyTable(pstate=0x00007f9f840066c0) at nodeModifyTable.c:2172
frame #6: 0x00000001088fbc12 postgres`ExecProcNodeFirst(node=0x00007f9f840066c0) at execProcnode.c:445
frame #7: 0x00000001088f5002 postgres`ExecProcNode(node=0x00007f9f840066c0) at executor.h:237
frame #8: 0x00000001088f0a31 postgres`ExecutePlan(estate=0x00007f9f84006318, planstate=0x00007f9f840066c0, use_parallel_mode=false, operation=CMD_UPDATE, sendTuples=false, numberTuples=0, direction=ForwardScanDirection, dest=0x00007f9f83005e40, execute_once=true) at execMain.c:1707
frame #9: 0x00000001088f08fc postgres`standard_ExecutorRun(queryDesc=0x00007f9f83005b18, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:364
frame #10: 0x00000001088f06c2 postgres`ExecutorRun(queryDesc=0x00007f9f83005b18, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:307
frame #11: 0x0000000108b2edfe postgres`ProcessQuery(plan=0x00007f9f830015b0, sourceText="UPDATE segfault SET i = 2;", params=0x0000000000000000, queryEnv=0x0000000000000000, dest=0x00007f9f83005e40, completionTag="") at pquery.c:161
frame #12: 0x0000000108b2de78 postgres`PortalRunMulti(portal=0x00007f9f82842518, isTopLevel=true, setHoldSnapshot=false, dest=0x00007f9f83005e40, altdest=0x00007f9f83005e40, completionTag="") at pquery.c:1286
frame #13: 0x0000000108b2d540 postgres`PortalRun(portal=0x00007f9f82842518, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x00007f9f83005e40, altdest=0x00007f9f83005e40, completionTag="") at pquery.c:799
frame #14: 0x0000000108b28a21 postgres`exec_simple_query(query_string="UPDATE segfault SET i = 2;") at postgres.c:1215
frame #15: 0x0000000108b27bb8 postgres`PostgresMain(argc=1, argv=0x00007f9f82815138, dbname="bussmann", username="bussmann") at postgres.c:4243
frame #16: 0x0000000108a655b4 postgres`BackendRun(port=0x00007f9f80e00910) at postmaster.c:4377
frame #17: 0x0000000108a649b8 postgres`BackendStartup(port=0x00007f9f80e00910) at postmaster.c:4068
frame #18: 0x0000000108a6385a postgres`ServerLoop at postmaster.c:1700
frame #19: 0x0000000108a61158 postgres`PostmasterMain(argc=3, argv=0x00007f9f81900580) at postmaster.c:1373
frame #20: 0x000000010896c219 postgres`main(argc=3, argv=0x00007f9f81900580) at main.c:228
frame #21: 0x00007fff517f9015 libdyld.dylib`start + 1

Interestingly, the debugger has no issue accessing the memory in question:
(Datum) value1 = 11
(Datum) value2 = 12
(bool) typByVal = false
(int) typLen = 8
(bool) res = false
(Size) size1 = 8
(Size) size2 = 8
(char *) s1 = 0x000000000000000b ""
(char *) s2 = 0x000000000000000c ""

How can this be investigated further?

The top of the stack trace is similar to the one in https://www.postgresql.org/message-id/20181101140216.GA2954%40hermes.hilbert.loc but I'm not sure these are actually related.

I was unable to reproduce the segfault with other index types then GIST nor w/o the opclasses provided by the btree_gist extension. However none of that specifically appears in the stack frame.

Further poking around the issue I came across the following:
# ALTER INDEX segfault_expr_idx SET (RECHECK_ON_UPDATE = off);
ERROR: unrecognized parameter "recheck_on_update"

According to the commit referred to earlier, this option should work for all index types, but apparently it does not for GIST. In reloptions.h:54 we have
> RELOPT_KIND_INDEX = RELOPT_KIND_BTREE|RELOPT_KIND_HASH|RELOPT_KIND_GIN|RELOPT_KIND_SPGIST
which is missing RELOPT_KIND_GIST and RELOPT_KIND_BRIN. Adding these at least fixes the possibility to set and use the parameter on the GIST index. Trivial patch for that attached.

Tobias

Attachment Content-Type Size
recheck_on_update.patch application/octet-stream 791 bytes
unknown_filename text/plain 4 bytes

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Alvaro Herrera 2018-11-07 14:49:57 Re: segfault with expression index, btree_gist and HOT Update
Previous Message Arthur Zakirov 2018-11-07 11:35:22 Re: BUG #15491: index on function not being used for full text search when querying through a view