This is an automated email from the ASF dual-hosted git repository. oppenheimer01 pushed a commit to branch cbdb-postgres-merge in repository https://gitbox.apache.org/repos/asf/cloudberry.git
commit 02f69e22e86256d0f860d330bd46e2409e1e5f9a Author: jangjang <[email protected]> AuthorDate: Thu Apr 30 04:30:08 2026 +0900 SIGSEGV in getCdbComponentInfo() when standby coordinator is on dedicated host (#1702) * Fix null dereference on dedicated hot standby coordinator getCdbComponentInfo() populates hostPrimaryCountHash with primary hosts only. When IS_HOT_STANDBY_QD() is true, mirror and standby hosts are also looked up in the hash but return NULL on dedicated standby nodes that host no primary segments. Replace Assert(found) with a null-safe check to prevent SIGSEGV. --- src/backend/cdb/cdbutil.c | 18 ++++++++++++++---- src/test/regress/expected/vacuum_gp.out | 9 ++++----- src/test/regress/sql/vacuum_gp.sql | 3 +++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/backend/cdb/cdbutil.c b/src/backend/cdb/cdbutil.c index a8c4e297f7e..cf924afae65 100644 --- a/src/backend/cdb/cdbutil.c +++ b/src/backend/cdb/cdbutil.c @@ -594,8 +594,13 @@ getCdbComponentInfo(void) continue; hsEntry = (HostPrimaryCountEntry *) hash_search(hostPrimaryCountHash, cdbInfo->config->hostname, HASH_FIND, &found); - Assert(found); - cdbInfo->hostPrimaryCount = hsEntry->segmentCount; + Assert(found || IS_HOT_STANDBY_QD()); + /* + * Standby and mirror entries can legitimately live on hosts that do not + * own any primary segments. In that case the lookup is absent and the + * count should be treated as zero instead of dereferencing a NULL entry. + */ + cdbInfo->hostPrimaryCount = found ? hsEntry->segmentCount : 0; } for (i = 0; i < component_databases->total_entry_dbs; i++) @@ -606,8 +611,13 @@ getCdbComponentInfo(void) continue; hsEntry = (HostPrimaryCountEntry *) hash_search(hostPrimaryCountHash, cdbInfo->config->hostname, HASH_FIND, &found); - Assert(found); - cdbInfo->hostPrimaryCount = hsEntry->segmentCount; + Assert(found || IS_HOT_STANDBY_QD()); + /* + * Standby and mirror entries can legitimately live on hosts that do not + * own any primary segments. In that case the lookup is absent and the + * count should be treated as zero instead of dereferencing a NULL entry. + */ + cdbInfo->hostPrimaryCount = found ? hsEntry->segmentCount : 0; } hash_destroy(hostPrimaryCountHash); diff --git a/src/test/regress/expected/vacuum_gp.out b/src/test/regress/expected/vacuum_gp.out index daeb2504559..cac825d0cd4 100644 --- a/src/test/regress/expected/vacuum_gp.out +++ b/src/test/regress/expected/vacuum_gp.out @@ -446,6 +446,8 @@ create table relcache_leak_in_motion(v1 int); NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'v1' as the Apache Cloudberry data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. insert into relcache_leak_in_motion values(generate_series(0, 10000)); +BEGIN; +SET LOCAL synchronous_commit = local; SELECT gp_inject_fault('interconnect_stop_recv_chunk', 'interrupt', dbid) FROM gp_segment_configuration WHERE content = -1 and role='p'; gp_inject_fault @@ -457,11 +459,8 @@ analyze relcache_leak_in_motion; ERROR: canceling statement due to user request SELECT gp_inject_fault('interconnect_stop_recv_chunk', 'reset', dbid) FROM gp_segment_configuration WHERE content = -1 and role='p'; - gp_inject_fault ------------------ - Success: -(1 row) - +ERROR: current transaction is aborted, commands ignored until end of transaction block +COMMIT; -- start_ignore drop table if exists relcache_leak_in_motion; -- end_ignore diff --git a/src/test/regress/sql/vacuum_gp.sql b/src/test/regress/sql/vacuum_gp.sql index 198a80f4a93..ed4bfe4f699 100644 --- a/src/test/regress/sql/vacuum_gp.sql +++ b/src/test/regress/sql/vacuum_gp.sql @@ -298,11 +298,14 @@ drop table if exists relcache_leak_in_motion; -- end_ignore create table relcache_leak_in_motion(v1 int); insert into relcache_leak_in_motion values(generate_series(0, 10000)); +BEGIN; +SET LOCAL synchronous_commit = local; SELECT gp_inject_fault('interconnect_stop_recv_chunk', 'interrupt', dbid) FROM gp_segment_configuration WHERE content = -1 and role='p'; analyze relcache_leak_in_motion; SELECT gp_inject_fault('interconnect_stop_recv_chunk', 'reset', dbid) FROM gp_segment_configuration WHERE content = -1 and role='p'; +COMMIT; -- start_ignore drop table if exists relcache_leak_in_motion; -- end_ignore --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
