Bug#16986 - Deadlock condition with MyISAM tables

Addendum fixes after changing the condition variable
for the global read lock.

The stress test suite revealed some deadlocks. Some were
related to the new condition variable (COND_global_read_lock)
and some were general problems with the global read lock.

It is now necessary to signal COND_global_read_lock whenever 
COND_refresh is signalled.

We need to wait for the release of a global read lock if one 
is set before every operation that requires a write lock.
But we must not wait if we have locked tables by LOCK TABLES.
After setting a global read lock a thread waits until all
write locks are released.


mysql-test/r/lock_multi.result:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Added test results.
mysql-test/t/lock_multi.test:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Added tests for possible deadlocks that did not occur
  with the stress test suite.
mysys/thr_lock.c:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Added a protection against an infinite loop that occurs
  with the test case for Bug #20662.
sql/lock.cc:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Signal COND_global_read_lock whenever COND_refresh
  is signalled by using the new function broadcast_refresh().
  Added the definition of a new function that signals 
  COND_global_read_lock whenever COND_refresh is signalled.
sql/mysql_priv.h:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Added a declaration for a new function that signals 
  COND_global_read_lock whenever COND_refresh is signalled.
sql/sql_base.cc:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Signal COND_global_read_lock whenever COND_refresh
  is signalled by using the new function broadcast_refresh().
sql/sql_handler.cc:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Signal COND_global_read_lock whenever COND_refresh
  is signalled by using the new function broadcast_refresh().
sql/sql_insert.cc:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Removed global read lock handling from inside of 
  INSERT DELAYED. It is handled on a higher level now.
sql/sql_parse.cc:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Wait for the release of a global read lock if one is set
  before every operation that requires a write lock.
  But don't wait if locked tables exist already.
sql/sql_table.cc:
  Bug#16986 - Deadlock condition with MyISAM tables
  Addendum fixes after changing the condition variable
  for the global read lock.
  Removed global read lock handling from inside of 
  CREATE TABLE. It is handled on a higher level now.
  Signal COND_global_read_lock whenever COND_refresh
  is signalled by using the new function broadcast_refresh().
This commit is contained in:
unknown 2006-06-26 19:14:35 +02:00
commit 1c2a13b894
10 changed files with 208 additions and 66 deletions

View file

@ -905,7 +905,7 @@ void unlock_table_name(THD *thd, TABLE_LIST *table_list)
if (table_list->table)
{
hash_delete(&open_cache, (byte*) table_list->table);
(void) pthread_cond_broadcast(&COND_refresh);
broadcast_refresh();
}
}
@ -997,9 +997,9 @@ end:
(default 0, which will unlock all tables)
NOTES
One must have a lock on LOCK_open when calling this
This function will send a COND_refresh signal to inform other threads
that the name locks are removed
One must have a lock on LOCK_open when calling this.
This function will broadcast refresh signals to inform other threads
that the name locks are removed.
RETURN
0 ok
@ -1013,7 +1013,7 @@ void unlock_table_names(THD *thd, TABLE_LIST *table_list,
table != last_table;
table= table->next_local)
unlock_table_name(thd,table);
pthread_cond_broadcast(&COND_refresh);
broadcast_refresh();
}
@ -1304,3 +1304,37 @@ bool make_global_read_lock_block_commit(THD *thd)
}
/*
Broadcast COND_refresh and COND_global_read_lock.
SYNOPSIS
broadcast_refresh()
void No parameters.
DESCRIPTION
Due to a bug in a threading library it could happen that a signal
did not reach its target. A condition for this was that the same
condition variable was used with different mutexes in
pthread_cond_wait(). Some time ago we changed LOCK_open to
LOCK_global_read_lock in global read lock handling. So COND_refresh
was used with LOCK_open and LOCK_global_read_lock.
We did now also change from COND_refresh to COND_global_read_lock
in global read lock handling. But now it is necessary to signal
both conditions at the same time.
NOTE
When signalling COND_global_read_lock within the global read lock
handling, it is not necessary to also signal COND_refresh.
RETURN
void
*/
void broadcast_refresh(void)
{
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_cond_broadcast(&COND_global_read_lock));
}