提交 41ce55bf 编写于 作者: D Denis Smirnov 提交者: Hubert Zhang

Fix tupdesc dangling pointer segfault in HashAgg

This problem manifests itself with HashAgg on the top of
DynamicIndexScan node and can cause a segmentation fault.

1. A HashAgg node initializes a tuple descriptor for its hash
slot using a reference from input tuples (coming from
DynamicIndexScan through a Sequence node).
2. At the end of every partition index scan in DynamicIndexScan
we unlink and free unused memory chunks and reset partition's
memory context. It causes a total destruction of all objects in
the context including partition index tuple descriptor used in a
HashAgg node.
As a result we get a dangling pointer in HashAgg on switching to
a new index partition during DynamicIndexScan that can cause a
segfault.
上级 2cb36320
......@@ -931,6 +931,7 @@ agg_hash_initial_pass(AggState *aggstate)
HashKey hashkey;
bool isNew;
HashAggEntry *entry;
TupleDesc slot_desc;
/* no more tuple. Done */
if (TupIsNull(outerslot))
......@@ -943,8 +944,16 @@ agg_hash_initial_pass(AggState *aggstate)
{
int size;
/* Initialize hashslot by cloning input slot. */
ExecSetSlotDescriptor(aggstate->hashslot, outerslot->tts_tupleDescriptor);
/*
* Initialize hashslot with a copy of an input slot.
* We should not use slot's tuple descriptor reference
* because DynamicXXX scan memory contexts are resetted
* at the end of every partition scan (that can cause
* dangling pointers).
*/
slot_desc = CreateTupleDescCopy(outerslot->tts_tupleDescriptor);
ExecSetSlotDescriptor(aggstate->hashslot, slot_desc);
ExecStoreAllNullTuple(aggstate->hashslot);
size = ((Agg *)aggstate->ss.ps.plan)->numCols * sizeof(HashKey);
......
......@@ -4127,6 +4127,36 @@ select * from pg_indexes where schemaname = 'public' and tablename like 'ti%';
(0 rows)
drop table ti;
-- Partitioned table with btree index and hash aggregate should use a correct
-- memory context for its tuples` descriptor
drop table if exists dis_tupdesc;
NOTICE: table "dis_tupdesc" does not exist, skipping
create table dis_tupdesc (a int, b int, c int)
distributed by (a)
partition by list (b)
(
partition p1 values (1),
partition p2 values (2),
default partition junk_data
);
NOTICE: CREATE TABLE will create partition "dis_tupdesc_1_prt_p1" for table "dis_tupdesc"
NOTICE: CREATE TABLE will create partition "dis_tupdesc_1_prt_p2" for table "dis_tupdesc"
NOTICE: CREATE TABLE will create partition "dis_tupdesc_1_prt_junk_data" for table "dis_tupdesc"
create index dis_tupdesc_idx on dis_tupdesc using btree (c);
insert into dis_tupdesc select i, i % 3, i % 4 from generate_series (1, 240) as i;
analyze dis_tupdesc;
set gp_segments_for_planner = 2;
set optimizer_segments = 2;
select distinct b from dis_tupdesc where c >= 2;
b
---
0
1
2
(3 rows)
reset gp_segments_for_planner;
reset optimizer_segments;
-- MPP-6611, make sure rename works with default partitions
create table it (i int, j int) partition by range(i)
subpartition by range(j) subpartition template(start(1) end(10) every(5))
......
......@@ -4140,6 +4140,36 @@ select * from pg_indexes where schemaname = 'public' and tablename like 'ti%';
(0 rows)
drop table ti;
-- Partitioned table with btree index and hash aggregate should use a correct
-- memory context for its tuples` descriptor
drop table if exists dis_tupdesc;
NOTICE: table "dis_tupdesc" does not exist, skipping
create table dis_tupdesc (a int, b int, c int)
distributed by (a)
partition by list (b)
(
partition p1 values (1),
partition p2 values (2),
default partition junk_data
);
NOTICE: CREATE TABLE will create partition "dis_tupdesc_1_prt_p1" for table "dis_tupdesc"
NOTICE: CREATE TABLE will create partition "dis_tupdesc_1_prt_p2" for table "dis_tupdesc"
NOTICE: CREATE TABLE will create partition "dis_tupdesc_1_prt_junk_data" for table "dis_tupdesc"
create index dis_tupdesc_idx on dis_tupdesc using btree (c);
insert into dis_tupdesc select i, i % 3, i % 4 from generate_series (1, 240) as i;
analyze dis_tupdesc;
set gp_segments_for_planner = 2;
set optimizer_segments = 2;
select distinct b from dis_tupdesc where c >= 2;
b
---
0
1
2
(3 rows)
reset gp_segments_for_planner;
reset optimizer_segments;
-- MPP-6611, make sure rename works with default partitions
create table it (i int, j int) partition by range(i)
subpartition by range(j) subpartition template(start(1) end(10) every(5))
......
......@@ -2138,6 +2138,26 @@ drop index ti_j_idx;
select * from pg_indexes where schemaname = 'public' and tablename like 'ti%';
drop table ti;
-- Partitioned table with btree index and hash aggregate should use a correct
-- memory context for its tuples` descriptor
drop table if exists dis_tupdesc;
create table dis_tupdesc (a int, b int, c int)
distributed by (a)
partition by list (b)
(
partition p1 values (1),
partition p2 values (2),
default partition junk_data
);
create index dis_tupdesc_idx on dis_tupdesc using btree (c);
insert into dis_tupdesc select i, i % 3, i % 4 from generate_series (1, 240) as i;
analyze dis_tupdesc;
set gp_segments_for_planner = 2;
set optimizer_segments = 2;
select distinct b from dis_tupdesc where c >= 2;
reset gp_segments_for_planner;
reset optimizer_segments;
-- MPP-6611, make sure rename works with default partitions
create table it (i int, j int) partition by range(i)
subpartition by range(j) subpartition template(start(1) end(10) every(5))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册