Skip to content

Commit 9569208

Browse files
committed
MDEV-37710 ASAN errors in find_type2 upon executing a procedure from sys schema
don't reload stored routines in the middle of the execution of a routine. we don't want different iterations of a loop to see diffefent definitions For this: remember Cversion in THD on the first sp cache lookup, after that only compare versions with this value not with Cversion.
1 parent 8df3524 commit 9569208

File tree

8 files changed

+84
-14
lines changed

8 files changed

+84
-14
lines changed

mysql-test/main/sp-bugs2.result

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#
2+
# MDEV-6610 Assertion `thd->is_error() || thd->killed' failed in mysql_execute_command on executing an SP with repeated CREATE TABLE .. SELECT
3+
#
14
CREATE TABLE t1 (i INT);
25
SET @a = 2;
36
CREATE TABLE IF NOT EXISTS t2 (i INT) ENGINE = MyISAM
@@ -94,4 +97,30 @@ CALL p1();
9497
# Clean up
9598
DROP FUNCTION cnt;
9699
DROP PROCEDURE p1;
100+
#
101+
# MDEV-37710 ASAN errors in find_type2 upon executing a procedure from sys schema
102+
#
103+
create procedure p1()
104+
begin
105+
declare found int;
106+
repeat
107+
set found = exists (select * from information_schema.routines where routine_name='f');
108+
if (sys.ps_is_consumer_enabled('events_waits_history_long') = 'yes') then
109+
select * from mysql.user;
110+
end if;
111+
select release_all_locks();
112+
until found end repeat;
113+
end$$
114+
select get_lock('p1', 300);
115+
get_lock('p1', 300)
116+
1
117+
call p1();
118+
connect con1,localhost,root,,;
119+
select get_lock('p1', 300);
120+
get_lock('p1', 300)
121+
1
122+
create function f() returns int return 1;
123+
connection default;
124+
drop function f;
125+
drop procedure p1;
97126
# End of 10.11 tests

mysql-test/main/sp-bugs2.test

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#
2-
# MDEV-6610 Assertion `thd->is_error() || thd->killed' failed in mysql_execute_command on executing an SP with repeated CREATE TABLE .. SELECT
3-
#
1+
--echo #
2+
--echo # MDEV-6610 Assertion `thd->is_error() || thd->killed' failed in mysql_execute_command on executing an SP with repeated CREATE TABLE .. SELECT
3+
--echo #
44
CREATE TABLE t1 (i INT);
55
SET @a = 2;
66

@@ -97,4 +97,32 @@ CALL p1();
9797
DROP FUNCTION cnt;
9898
DROP PROCEDURE p1;
9999

100+
--echo #
101+
--echo # MDEV-37710 ASAN errors in find_type2 upon executing a procedure from sys schema
102+
--echo #
103+
delimiter $$;
104+
create procedure p1()
105+
begin
106+
declare found int;
107+
repeat
108+
set found = exists (select * from information_schema.routines where routine_name='f');
109+
if (sys.ps_is_consumer_enabled('events_waits_history_long') = 'yes') then
110+
select * from mysql.user;
111+
end if;
112+
select release_all_locks();
113+
until found end repeat;
114+
end$$
115+
delimiter ;$$
116+
select get_lock('p1', 300);
117+
--send call p1()
118+
--connect con1,localhost,root,,
119+
select get_lock('p1', 300);
120+
create function f() returns int return 1;
121+
--connection default
122+
--disable_result_log
123+
--reap
124+
--enable_result_log
125+
drop function f;
126+
drop procedure p1;
127+
100128
--echo # End of 10.11 tests

sql/sp.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ Sp_handler::sp_drop_routine_internal(THD *thd,
11271127
sp_cache **spc= get_cache(thd);
11281128
DBUG_ASSERT(spc);
11291129
if ((sp= sp_cache_lookup(spc, name)))
1130-
sp_cache_flush_obsolete(spc, &sp);
1130+
sp_cache_flush_obsolete(spc, &sp, sp_cache_version());
11311131
/* Drop statistics for this stored program from performance schema. */
11321132
MYSQL_DROP_SP(type(), name->m_db.str, static_cast<uint>(name->m_db.length),
11331133
name->m_name.str, static_cast<uint>(name->m_name.length));
@@ -2818,10 +2818,11 @@ int Sp_handler::sp_cache_routine(THD *thd,
28182818
DBUG_ASSERT(spc);
28192819

28202820
*sp= sp_cache_lookup(spc, name);
2821+
thd->set_sp_cache_version_if_needed(sp_cache_version());
28212822

28222823
if (*sp)
28232824
{
2824-
sp_cache_flush_obsolete(spc, sp);
2825+
sp_cache_flush_obsolete(spc, sp, thd->sp_cache_version());
28252826
if (*sp)
28262827
DBUG_RETURN(SP_OK);
28272828
}

sql/sp_cache.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,9 @@ void sp_cache_invalidate()
231231
inside SP'.
232232
*/
233233

234-
void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp)
234+
void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp, ulong version)
235235
{
236-
if ((*sp)->sp_cache_version() < Cversion && !(*sp)->is_invoked())
236+
if ((*sp)->sp_cache_version() < version)
237237
{
238238
(*cp)->remove(*sp);
239239
*sp= NULL;

sql/sp_cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void sp_cache_clear(sp_cache **cp);
5959
void sp_cache_insert(sp_cache **cp, sp_head *sp);
6060
sp_head *sp_cache_lookup(sp_cache **cp, const Database_qualified_name *name);
6161
void sp_cache_invalidate();
62-
void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp);
62+
void sp_cache_flush_obsolete(sp_cache **cp, sp_head **sp, ulong version);
6363
ulong sp_cache_version();
6464
void sp_cache_enforce_limit(sp_cache *cp, ulong upper_limit_for_elements);
6565

sql/sql_base.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3186,7 +3186,7 @@ static bool
31863186
check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt,
31873187
sp_head *sp)
31883188
{
3189-
ulong spc_version= sp_cache_version();
3189+
ulong spc_version= thd->sp_cache_version();
31903190
/* sp is NULL if there is no such routine. */
31913191
ulong version= sp ? sp->sp_cache_version() : spc_version;
31923192
/*
@@ -3196,7 +3196,7 @@ check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt,
31963196
Sic: version != spc_version <--> sp is not NULL.
31973197
*/
31983198
if (rt->m_sp_cache_version != version ||
3199-
(version != spc_version && !sp->is_invoked()))
3199+
(version < spc_version && !sp->is_invoked()))
32003200
{
32013201
if (thd->m_reprepare_observer &&
32023202
thd->m_reprepare_observer->report_error(thd))

sql/sql_class.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,16 +2449,16 @@ struct wait_for_commit
24492449

24502450
class Sp_caches
24512451
{
2452+
protected:
2453+
ulong m_sp_cache_version;
24522454
public:
24532455
sp_cache *sp_proc_cache;
24542456
sp_cache *sp_func_cache;
24552457
sp_cache *sp_package_spec_cache;
24562458
sp_cache *sp_package_body_cache;
24572459
Sp_caches()
2458-
:sp_proc_cache(NULL),
2459-
sp_func_cache(NULL),
2460-
sp_package_spec_cache(NULL),
2461-
sp_package_body_cache(NULL)
2460+
:m_sp_cache_version(0), sp_proc_cache(NULL), sp_func_cache(NULL),
2461+
sp_package_spec_cache(NULL), sp_package_body_cache(NULL)
24622462
{ }
24632463
~Sp_caches()
24642464
{
@@ -2481,6 +2481,16 @@ class Sp_caches
24812481
Don't delete cache objects itself.
24822482
*/
24832483
void sp_caches_empty();
2484+
ulong sp_cache_version() const
2485+
{
2486+
DBUG_ASSERT(m_sp_cache_version);
2487+
return m_sp_cache_version;
2488+
}
2489+
void set_sp_cache_version_if_needed(ulong version)
2490+
{
2491+
if (!m_sp_cache_version)
2492+
m_sp_cache_version= version;
2493+
}
24842494
};
24852495

24862496

sql/sql_parse.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7772,6 +7772,8 @@ void THD::reset_for_next_command(bool do_clear_error)
77727772

77737773
save_prep_leaf_list= false;
77747774

7775+
m_sp_cache_version= 0;
7776+
77757777
#ifdef WITH_WSREP
77767778
#if !defined(DBUG_OFF)
77777779
if (mysql_bin_log.is_open())

0 commit comments

Comments
 (0)