MDEV-29605 Reset queued ping info of all spider connections associated with a closed spider handler

A spider_conn may outlive its associated ha_spider (in the field
queued_ping_spider) used for connecting to and pinging the data
node (a call to spider_db_ping(), guarded by the boolean field
queued_ping). In a call to ha_spider::close() (which is often preceded
with the deletion of the ha_spider itself), many cleanups happen,
including freeing the associated spider_share, which is used by the
spider_conn in spider_db_ping. Therefore it is necessary to reset both
the queued_ping_spider and queued_ping fields, so that any further
spider interaction with the data node will not trigger the call using
the ha_spider including its freed spider_share.

Also out of caution added an assert and internal error in case a
connection has not been established (the db_conn field of type
MYSQL * is NULL), and attempt to connect is skipped because both
queued_connect and queued_ping are false. Note that this unlikely (if
not impossible) scenario would not be a regression caused by this
change, as it strictly falls under the scenario of this bug.
This commit is contained in:
Yuchen Pei 2025-01-15 18:10:16 +11:00
parent f862fe8b2b
commit 18a44b4298
No known key found for this signature in database
GPG key ID: 3DD1B35105743563
4 changed files with 71 additions and 0 deletions

View file

@ -513,6 +513,28 @@ static void spider_update_current_trx_ha_with_freed_share(SPIDER_SHARE *share)
}
}
/*
Given an ha_spider that is being closed, reset the queued ping info
of SPIDER_CONN of the current spider trx that has the given
ha_spider as the queued_ping_spider.
*/
static void spider_reset_conn_queued_ping(ha_spider *spider)
{
SPIDER_TRX *trx= spider_current_trx;
if (trx)
{
for (uint i= 0; i < trx->trx_conn_hash.records; i++)
{
SPIDER_CONN *conn= (SPIDER_CONN *) my_hash_element(&trx->trx_conn_hash, i);
if (conn->queued_ping_spider == spider)
{
conn->queued_ping= FALSE;
conn->queued_ping_spider= NULL;
}
}
}
}
int ha_spider::close()
{
int error_num = 0, roop_count, error_num2;
@ -622,6 +644,7 @@ int ha_spider::close()
result_list.tmp_sqls = NULL;
}
spider_reset_conn_queued_ping(this);
spider_update_current_trx_ha_with_freed_share(share);
spider_free_share(share);
is_clone = FALSE;

View file

@ -0,0 +1,19 @@
for master_1
for child2
for child3
set spider_same_server_link= 1;
CREATE USER spider@localhost IDENTIFIED BY 'pwd';
GRANT ALL ON test.* TO spider@localhost;
CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'spider', password 'pwd');
SET autocommit=0;
set @old_init_connect=@@global.init_connect;
set global init_connect="dummy";
CREATE TABLE t ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"' AS SELECT 1;
Got one of the listed errors
set global init_connect=@old_init_connect;
drop server srv;
drop user spider@localhost;
for master_1
for child2
for child3

View file

@ -0,0 +1,25 @@
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
set spider_same_server_link= 1;
CREATE USER spider@localhost IDENTIFIED BY 'pwd';
GRANT ALL ON test.* TO spider@localhost;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql
OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'spider', password 'pwd');
SET autocommit=0;
set @old_init_connect=@@global.init_connect;
set global init_connect="dummy";
--error ER_NET_ERROR_ON_WRITE,12701
CREATE TABLE t ENGINE=Spider COMMENT='WRAPPER "mysql",srv "srv",TABLE "t"' AS SELECT 1;
set global init_connect=@old_init_connect;
drop server srv;
drop user spider@localhost;
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log

View file

@ -2119,6 +2119,10 @@ int spider_db_mbase::exec_query(
general_log_write(current_thd, COM_QUERY, tmp_query_str.ptr(),
tmp_query_str.length());
}
/* There should be a live connection to the data node */
DBUG_ASSERT(db_conn);
if (!db_conn)
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
if (!spider_param_dry_access())
{
error_num = mysql_real_query(db_conn, query, length);