MDEV-8869: Potential lock_sys->mutex deadlock

In wsrep BF we have already took lock_sys and trx
mutex either on wsrep_abort_transaction() or
before wsrep_kill_victim(). In replication we
could own lock_sys mutex taken in
lock_deadlock_check_and_resolve().
This commit is contained in:
Jan Lindström 2015-12-21 16:36:26 +02:00
commit 080da551ea
8 changed files with 164 additions and 27 deletions

View file

@ -4358,29 +4358,46 @@ innobase_kill_query(
#endif /* WITH_WSREP */
trx = thd_to_trx(thd);
if (trx) {
if (trx && trx->lock.wait_lock) {
/* In wsrep BF we have already took lock_sys and trx
mutex either on wsrep_abort_transaction() or
before wsrep_kill_victim() */
before wsrep_kill_victim(). In replication we
could own lock_sys mutex taken in
lock_deadlock_check_and_resolve(). */
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
WSREP_DEBUG("Killing victim trx %p BF %d trx BF %d trx_id " TRX_ID_FMT " ABORT %d thd %p"
" current_thd %p BF %d wait_lock_modes: %s\n",
trx, wsrep_thd_is_BF(trx->mysql_thd, FALSE),
wsrep_thd_is_BF(thd, FALSE),
trx->id, trx->abort_type,
trx->mysql_thd,
current_thd,
wsrep_thd_is_BF(current_thd, FALSE),
lock_get_info(trx->lock.wait_lock).c_str());
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
trx->abort_type == TRX_SERVER_ABORT) {
ut_ad(!lock_mutex_own());
ut_ad(!trx_mutex_own(trx));
lock_mutex_enter();
}
if (trx->abort_type != TRX_WSREP_ABORT) {
trx_mutex_enter(trx);
}
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(trx));
/* We did dirty read above in case when abort is not
from wsrep. */
if (trx->lock.wait_lock) {
lock_cancel_waiting_and_release(trx->lock.wait_lock);
}
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (trx->abort_type != TRX_WSREP_ABORT) {
trx_mutex_exit(trx);
}
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
trx->abort_type == TRX_SERVER_ABORT) {
lock_mutex_exit();
}
}
@ -17537,12 +17554,12 @@ wsrep_abort_transaction(
if (victim_trx) {
lock_mutex_enter();
trx_mutex_enter(victim_trx);
victim_trx->wsrep_abort = TRUE;
victim_trx->abort_type = TRX_WSREP_ABORT;
int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
victim_trx, signal);
trx_mutex_exit(victim_trx);
lock_mutex_exit();
victim_trx->wsrep_abort = FALSE;
victim_trx->abort_type = TRX_SERVER_ABORT;
wsrep_srv_conc_cancel_wait(victim_trx);
DBUG_RETURN(rcode);
} else {