summaryrefslogtreecommitdiff
path: root/sql/rpl_parallel.cc
diff options
context:
space:
mode:
authorKristian Nielsen <knielsen@knielsen-hq.org>2015-02-24 14:03:14 +0100
committerKristian Nielsen <knielsen@knielsen-hq.org>2015-02-24 14:39:15 +0100
commita227cf8046c1dbf4c8689c9923d9b3c9e0abc165 (patch)
tree292946ef1c4fa3cbb689d1ae14a184689fbedb3f /sql/rpl_parallel.cc
parent79e9ff44d18f5fb986870cfac17fc661fb098098 (diff)
downloadmariadb-git-a227cf8046c1dbf4c8689c9923d9b3c9e0abc165.tar.gz
MDEV-7335: Potential parallel slave deadlock with specific binlog corruption
If somehow the COMMIT or XID event in an event group was missing, the code in parallel replication to handle this was not sufficient, leading to server deadlock.
Diffstat (limited to 'sql/rpl_parallel.cc')
-rw-r--r--sql/rpl_parallel.cc31
1 files changed, 17 insertions, 14 deletions
diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc
index 46c3e4aaaf4..c6bb974f62f 100644
--- a/sql/rpl_parallel.cc
+++ b/sql/rpl_parallel.cc
@@ -640,7 +640,7 @@ handle_rpl_parallel_thread(void *arg)
}
DBUG_ASSERT(qev->typ==rpl_parallel_thread::queued_event::QUEUED_EVENT);
- thd->rgi_slave= group_rgi= rgi;
+ thd->rgi_slave= rgi;
gco= rgi->gco;
/* Handle a new event group, which will be initiated by a GTID event. */
if ((event_type= qev->ev->get_type_code()) == GTID_EVENT)
@@ -657,6 +657,21 @@ handle_rpl_parallel_thread(void *arg)
}
});
+ if(unlikely(thd->wait_for_commit_ptr) && group_rgi != NULL)
+ {
+ /*
+ This indicates that we get a new GTID event in the middle of
+ a not completed event group. This is corrupt binlog (the master
+ will never write such binlog), so it does not happen unless
+ someone tries to inject wrong crafted binlog, but let us still
+ try to handle it somewhat nicely.
+ */
+ group_rgi->cleanup_context(thd, true);
+ finish_event_group(rpt, group_rgi->gtid_sub_id,
+ group_rgi->parallel_entry, group_rgi);
+ rpt->loc_free_rgi(group_rgi);
+ }
+
in_event_group= true;
/*
If the standalone flag is set, then this event group consists of a
@@ -742,19 +757,6 @@ handle_rpl_parallel_thread(void *arg)
unlock_or_exit_cond(thd, &entry->LOCK_parallel_entry,
&did_enter_cond, &old_stage);
- if(thd->wait_for_commit_ptr)
- {
- /*
- This indicates that we get a new GTID event in the middle of
- a not completed event group. This is corrupt binlog (the master
- will never write such binlog), so it does not happen unless
- someone tries to inject wrong crafted binlog, but let us still
- try to handle it somewhat nicely.
- */
- rgi->cleanup_context(thd, true);
- thd->wait_for_commit_ptr->unregister_wait_for_prior_commit();
- thd->wait_for_commit_ptr->wakeup_subsequent_commits(rgi->worker_error);
- }
thd->wait_for_commit_ptr= &rgi->commit_orderer;
if (opt_gtid_ignore_duplicates)
@@ -780,6 +782,7 @@ handle_rpl_parallel_thread(void *arg)
}
}
+ group_rgi= rgi;
group_ending= is_group_ending(qev->ev, event_type);
if (group_ending && likely(!rgi->worker_error))
{