Skip to content

Commit fe78495

Browse files
dmitryshulgavuvova
authored andcommitted
MDEV-16708: fixed assert firing in the method THD::reset_for_the_next_command
1 parent 994e3f4 commit fe78495

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

sql/sql_binlog.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,28 @@ void mysql_client_binlog_statement(THD* thd)
354354
(ev->flags & LOG_EVENT_SKIP_REPLICATION_F ?
355355
OPTION_SKIP_REPLICATION : 0);
356356

357-
err= ev->apply_event(rgi);
357+
{
358+
/*
359+
For conventional statements thd->lex points to thd->main_lex, that is
360+
thd->lex == &thd->main_lex. On the other hand, for prepared statement
361+
thd->lex points to the LEX object explicitly allocated for execution
362+
of the prepared statement and in this case thd->lex != &thd->main_lex.
363+
On handling the BINLOG statement, invocation of ev->apply_event(rgi)
364+
initiates the following sequence of calls
365+
Rows_log_event::do_apply_event -> THD::reset_for_next_command
366+
Since the method THD::reset_for_next_command() contains assert
367+
DBUG_ASSERT(lex == &main_lex)
368+
this sequence of calls results in crash when a binlog event is
369+
applied in PS mode. So, reset the current lex temporary to point to
370+
thd->main_lex before running ev->apply_event() and restore its
371+
original value on return.
372+
*/
373+
LEX *backup_lex;
358374

375+
thd->backup_and_reset_current_lex(&backup_lex);
376+
err= ev->apply_event(rgi);
377+
thd->restore_current_lex(backup_lex);
378+
}
359379
thd->variables.option_bits=
360380
(thd->variables.option_bits & ~OPTION_SKIP_REPLICATION) |
361381
save_skip_replication;

sql/sql_class.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5453,6 +5453,33 @@ class THD: public THD_count, /* this must be first */
54535453
return (variables.old_behavior & OLD_MODE_UTF8_IS_UTF8MB3 ?
54545454
MY_UTF8_IS_UTF8MB3 : 0);
54555455
}
5456+
5457+
/**
5458+
Save current lex to the output parameter and reset it to point to
5459+
main_lex. This method is called from mysql_client_binlog_statement()
5460+
to temporary
5461+
5462+
@param[out] backup_lex original value of current lex
5463+
*/
5464+
5465+
void backup_and_reset_current_lex(LEX **backup_lex)
5466+
{
5467+
*backup_lex= lex;
5468+
lex= &main_lex;
5469+
}
5470+
5471+
5472+
/**
5473+
Restore current lex to its original value it had before calling the method
5474+
backup_and_reset_current_lex().
5475+
5476+
@param backup_lex original value of current lex
5477+
*/
5478+
5479+
void restore_current_lex(LEX *backup_lex)
5480+
{
5481+
lex= backup_lex;
5482+
}
54565483
};
54575484

54585485

0 commit comments

Comments
 (0)