1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Bug#49020 Semi-sync master crashed with free_pool == NULL, assertion `free_pool_'

Before this patch, semisync assumed transactions running in parallel
can not be larger than max_connections, but this is not true when
the event scheduler is executing events, and cause semisync run out
of preallocated transaction nodes.

Fix the problem by allocating transaction nodes dynamically.

This patch also fixed a possible deadlock when running UNINSTALL
PLUGIN rpl_semi_sync_master and updating in parallel. Fixed by
releasing the internal Delegate lock before unlock the plugins.

mysql-test/suite/rpl/t/rpl_semi_sync_event.test:
  Add test case for bug#49020
plugin/semisync/semisync_master.cc:
  Allocating TranxNode dynamically
plugin/semisync/semisync_master.h:
  Allocating TranxNode dynamically
sql/rpl_handler.cc:
  Unlock plugins after we have released the Delegate lock to avoid possible deadlock when uninstalling semisync master plugin and doing update in parallel.
This commit is contained in:
He Zhenxing
2009-12-04 09:46:33 +08:00
parent a02972d820
commit c926610d7c
7 changed files with 213 additions and 85 deletions

View File

@@ -137,28 +137,53 @@ void delegates_destroy()
*/
#define FOREACH_OBSERVER(r, f, thd, args) \
param.server_id= thd->server_id; \
/*
Use a struct to make sure that they are allocated adjacent, check
delete_dynamic().
*/ \
struct { \
DYNAMIC_ARRAY plugins; \
/* preallocate 8 slots */ \
plugin_ref plugins_buffer[8]; \
} s; \
DYNAMIC_ARRAY *plugins= &s.plugins; \
plugin_ref *plugins_buffer= s.plugins_buffer; \
my_init_dynamic_array2(plugins, sizeof(plugin_ref), \
plugins_buffer, 8, 8); \
read_lock(); \
Observer_info_iterator iter= observer_info_iter(); \
Observer_info *info= iter++; \
for (; info; info= iter++) \
{ \
plugin_ref plugin= \
my_plugin_lock(thd, &info->plugin); \
my_plugin_lock(0, &info->plugin); \
if (!plugin) \
{ \
r= 1; \
/* plugin is not intialized or deleted, this is not an error */ \
r= 0; \
break; \
} \
insert_dynamic(plugins, (uchar *)&plugin); \
if (((Observer *)info->observer)->f \
&& ((Observer *)info->observer)->f args) \
{ \
r= 1; \
plugin_unlock(thd, plugin); \
sql_print_error("Run function '" #f "' in plugin '%s' failed", \
info->plugin_int->name.str); \
break; \
} \
plugin_unlock(thd, plugin); \
} \
unlock()
unlock(); \
/*
Unlock plugins should be done after we released the Delegate lock
to avoid possible deadlock when this is the last user of the
plugin, and when we unlock the plugin, it will try to
deinitialize the plugin, which will try to lock the Delegate in
order to remove the observers.
*/ \
plugin_unlock_list(0, (plugin_ref*)plugins->buffer, \
plugins->elements); \
delete_dynamic(plugins)
int Trans_delegate::after_commit(THD *thd, bool all)