From d75a41cc630a986c08b4c8f9545fc4fba4609bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Nordstr=C3=B6m?= Date: Wed, 20 Nov 2024 12:29:16 +0100 Subject: [PATCH] Fix crash when converting to Hypercore TAM The tuple sort state used for compression was created with a reference to a tuple descriptor in a relcache entry. If this relcache entry is invalidated, the tuple sort state becomes corrupt. This caused occasional crashes when converting a chunk to using Hypercore TAM (i.e., compressing). Fix this by always making a copy of the tuple descriptor when creating the tuple sort state. --- tsl/src/compression/compression.c | 5 ++++- tsl/src/hypercore/hypercore_handler.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tsl/src/compression/compression.c b/tsl/src/compression/compression.c index d336c19eadf..05ec3f2e3e1 100644 --- a/tsl/src/compression/compression.c +++ b/tsl/src/compression/compression.c @@ -560,7 +560,10 @@ compression_create_tuplesort_state(CompressionSettings *settings, Relation rel) &nulls_first[n]); } - return tuplesort_begin_heap(tupdesc, + /* Make a copy of the tuple descriptor so that it is allocated on the same + * memory context as the tuple sort instead of pointing into the relcache + * entry that could be blown away. */ + return tuplesort_begin_heap(CreateTupleDescCopy(tupdesc), n_keys, sort_keys, sort_operators, diff --git a/tsl/src/hypercore/hypercore_handler.c b/tsl/src/hypercore/hypercore_handler.c index 66de3b3b830..e01c5466c6e 100644 --- a/tsl/src/hypercore/hypercore_handler.c +++ b/tsl/src/hypercore/hypercore_handler.c @@ -3464,6 +3464,14 @@ convert_to_hypercore_finish(Oid relid) return; } +#ifdef USE_ASSERT_CHECKING + /* Blow away relation cache to test that the tuple sort state works across + * relcache invalidations. Previously there was sometimes a crash here + * because the tuple sort state had a reference to a tuple descriptor in + * the relcache. */ + RelationCacheInvalidate(false); +#endif + Chunk *chunk = ts_chunk_get_by_relid(conversionstate->relid, true); Relation relation = table_open(conversionstate->relid, AccessShareLock); TupleDesc tupdesc = RelationGetDescr(relation);