Fixed mutexes lock order in maria_close(): LOCK_trn_list -> MARIA_SHARE::intern_lock (then will be WL to revert the order).

(BUG#40981 Maria: deadlock between checkpoint and maria_close() when freeing state info)

storage/maria/ma_checkpoint.c:
  The argument added to the function to use it in maria_close().
storage/maria/ma_close.c:
  Locking/unlocking MARIA_SHARE::intern_lock added to use correct order of the mutexes taking.
storage/maria/ma_state.c:
  Removed assert becase now we have externally locked mutex in maria_close().
  The argument added to the _ma_remove_not_visible_states_with_lock() to use it in maria_close().
  _ma_remove_not_visible_states_with_lock() fixed tio be usable from maria_chk where transaction manager is not initialized.
storage/maria/ma_state.h:
  The argument added to the function to use it in maria_close().
storage/maria/maria_def.h:
  Fixed comment to the variable.
storage/maria/trnman.c:
  The debugging assert added.
  New function to detect transaction manager initialization added (maria_chk do not initialize it).
storage/maria/trnman_public.h:
  New function to detect transaction manager initialization added (maria_chk do not initialize it).
This commit is contained in:
unknown 2008-12-08 22:09:59 +02:00
commit c9b0c5a15c
7 changed files with 49 additions and 18 deletions

View file

@ -166,7 +166,6 @@ MARIA_STATE_HISTORY
if (all && parent == &org_history->next)
{
DBUG_ASSERT(trnman_is_locked == 0);
/* There is only one state left. Delete this if it's visible for all */
if (last_trid < trnman_get_min_trid())
{
@ -181,6 +180,11 @@ MARIA_STATE_HISTORY
/**
@brief Remove not used state history
@param share Maria table information
@param all 1 if we should delete the first state if it's
visible for all. For the moment this is only used
on close() of table.
@notes
share and trnman are not locked.
@ -189,14 +193,19 @@ MARIA_STATE_HISTORY
takes share->intern_lock.
*/
void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share)
void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share,
my_bool all)
{
trnman_lock();
my_bool is_lock_trman;
if ((is_lock_trman= trman_is_inited()))
trnman_lock();
pthread_mutex_lock(&share->intern_lock);
share->state_history= _ma_remove_not_visible_states(share->state_history, 0,
1);
share->state_history= _ma_remove_not_visible_states(share->state_history,
all, 1);
pthread_mutex_unlock(&share->intern_lock);
trnman_unlock();
if (is_lock_trman)
trnman_unlock();
}