Bug#36443 Server crashes when executing insert when insert trigger on table
The crash appeared to be a result of allocating an instance of Discrete_interval automatically that that was referred in out-of-declaration scope. Fixed with correcting backing up and restoring scheme of auto_inc_intervals_forced, introduced by bug#33029, by means of shallow copying; added simulation code that forces executing those fixes of the former bug that targeted at master-and-slave having incompatible bug#33029-prone versions. mysql-test/suite/bugs/r/rpl_bug33029.result: new results file mysql-test/suite/bugs/t/rpl_bug33029.test: test merely checks no crash happens on slave. sql/slave.cc: forcing to execute special logics implemented for bug#33029 if simulate_bug33029 the debug option is set. sql/sql_class.cc: swaps of backed and the actual auto_inc_intervals_forced basing on shallow coping. sql/structs.h: Removing the deep _copy() and methods associated with it; adding methods to Discrete_intervals_list: private `=', copy constructor to prevent using; private set_members(); public copy_shallow(), swap(), get_{head, tail, current}(); empty_no_free() through set_members().
This commit is contained in:
parent
0a68dd1d3f
commit
e66ba2a74b
15
mysql-test/suite/bugs/r/rpl_bug33029.result
Normal file
15
mysql-test/suite/bugs/r/rpl_bug33029.result
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
stop slave;
|
||||||
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
|
reset master;
|
||||||
|
reset slave;
|
||||||
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
|
start slave;
|
||||||
|
create table `t1` (`id` int not null auto_increment primary key);
|
||||||
|
create trigger `trg` before insert on `t1` for each row begin end;
|
||||||
|
set @@global.debug="+d,simulate_bug33029";
|
||||||
|
stop slave;
|
||||||
|
start slave;
|
||||||
|
insert into `t1` values ();
|
||||||
|
select * from t1;
|
||||||
|
id
|
||||||
|
1
|
25
mysql-test/suite/bugs/t/rpl_bug33029.test
Normal file
25
mysql-test/suite/bugs/t/rpl_bug33029.test
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# Bug #36443 Server crashes when executing insert when insert trigger on table
|
||||||
|
#
|
||||||
|
# Emulating the former bug#33029 situation to see that there is no crash anymore.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
source include/master-slave.inc;
|
||||||
|
|
||||||
|
create table `t1` (`id` int not null auto_increment primary key);
|
||||||
|
create trigger `trg` before insert on `t1` for each row begin end;
|
||||||
|
|
||||||
|
sync_slave_with_master;
|
||||||
|
set @@global.debug="+d,simulate_bug33029";
|
||||||
|
|
||||||
|
stop slave;
|
||||||
|
start slave;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
|
||||||
|
insert into `t1` values ();
|
||||||
|
|
||||||
|
sync_slave_with_master;
|
||||||
|
select * from t1;
|
||||||
|
|
@ -4136,6 +4136,7 @@ bool rpl_master_erroneous_autoinc(THD *thd)
|
|||||||
if (active_mi && active_mi->rli.sql_thd == thd)
|
if (active_mi && active_mi->rli.sql_thd == thd)
|
||||||
{
|
{
|
||||||
Relay_log_info *rli= &active_mi->rli;
|
Relay_log_info *rli= &active_mi->rli;
|
||||||
|
DBUG_EXECUTE_IF("simulate_bug33029", return TRUE;);
|
||||||
return rpl_master_has_bug(rli, 33029, FALSE);
|
return rpl_master_has_bug(rli, 33029, FALSE);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -2882,8 +2882,8 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|||||||
*/
|
*/
|
||||||
if (rpl_master_erroneous_autoinc(this))
|
if (rpl_master_erroneous_autoinc(this))
|
||||||
{
|
{
|
||||||
backup->auto_inc_intervals_forced= auto_inc_intervals_forced;
|
DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
|
||||||
auto_inc_intervals_forced.empty();
|
auto_inc_intervals_forced.swap(&backup->auto_inc_intervals_forced);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2931,8 +2931,8 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
|||||||
*/
|
*/
|
||||||
if (rpl_master_erroneous_autoinc(this))
|
if (rpl_master_erroneous_autoinc(this))
|
||||||
{
|
{
|
||||||
auto_inc_intervals_forced= backup->auto_inc_intervals_forced;
|
backup->auto_inc_intervals_forced.swap(&auto_inc_intervals_forced);
|
||||||
backup->auto_inc_intervals_forced.empty();
|
DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -314,31 +314,22 @@ private:
|
|||||||
*/
|
*/
|
||||||
Discrete_interval *current;
|
Discrete_interval *current;
|
||||||
uint elements; // number of elements
|
uint elements; // number of elements
|
||||||
|
void set_members(Discrete_interval *h, Discrete_interval *t,
|
||||||
|
Discrete_interval *c, uint el)
|
||||||
|
{
|
||||||
|
head= h;
|
||||||
|
tail= t;
|
||||||
|
current= c;
|
||||||
|
elements= el;
|
||||||
|
}
|
||||||
|
void operator=(Discrete_intervals_list &); /* prevent use of these */
|
||||||
|
Discrete_intervals_list(const Discrete_intervals_list &);
|
||||||
|
|
||||||
/* helper function for copy construct and assignment operator */
|
|
||||||
void copy_(const Discrete_intervals_list& from)
|
|
||||||
{
|
|
||||||
for (Discrete_interval *i= from.head; i; i= i->next)
|
|
||||||
{
|
|
||||||
Discrete_interval j= *i;
|
|
||||||
append(&j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
|
Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
|
||||||
Discrete_intervals_list(const Discrete_intervals_list& from)
|
|
||||||
{
|
|
||||||
copy_(from);
|
|
||||||
}
|
|
||||||
void operator=(const Discrete_intervals_list& from)
|
|
||||||
{
|
|
||||||
empty();
|
|
||||||
copy_(from);
|
|
||||||
}
|
|
||||||
void empty_no_free()
|
void empty_no_free()
|
||||||
{
|
{
|
||||||
head= current= NULL;
|
set_members(NULL, NULL, NULL, 0);
|
||||||
elements= 0;
|
|
||||||
}
|
}
|
||||||
void empty()
|
void empty()
|
||||||
{
|
{
|
||||||
@ -350,7 +341,24 @@ public:
|
|||||||
}
|
}
|
||||||
empty_no_free();
|
empty_no_free();
|
||||||
}
|
}
|
||||||
|
void copy_shallow(const Discrete_intervals_list * dli)
|
||||||
|
{
|
||||||
|
head= dli->get_head();
|
||||||
|
tail= dli->get_tail();
|
||||||
|
current= dli->get_current();
|
||||||
|
elements= dli->nb_elements();
|
||||||
|
}
|
||||||
|
void swap (Discrete_intervals_list * dli)
|
||||||
|
{
|
||||||
|
Discrete_interval *h, *t, *c;
|
||||||
|
uint el;
|
||||||
|
h= dli->get_head();
|
||||||
|
t= dli->get_tail();
|
||||||
|
c= dli->get_current();
|
||||||
|
el= dli->nb_elements();
|
||||||
|
dli->copy_shallow(this);
|
||||||
|
set_members(h, t, c, el);
|
||||||
|
}
|
||||||
const Discrete_interval* get_next()
|
const Discrete_interval* get_next()
|
||||||
{
|
{
|
||||||
Discrete_interval *tmp= current;
|
Discrete_interval *tmp= current;
|
||||||
@ -364,4 +372,7 @@ public:
|
|||||||
ulonglong minimum() const { return (head ? head->minimum() : 0); };
|
ulonglong minimum() const { return (head ? head->minimum() : 0); };
|
||||||
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
|
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
|
||||||
uint nb_elements() const { return elements; }
|
uint nb_elements() const { return elements; }
|
||||||
|
Discrete_interval* get_head() const { return head; };
|
||||||
|
Discrete_interval* get_tail() const { return tail; };
|
||||||
|
Discrete_interval* get_current() const { return current; };
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user