summaryrefslogtreecommitdiff
path: root/sql/rpl_handler.cc
diff options
context:
space:
mode:
authorHe Zhenxing <zhenxing.he@sun.com>2009-12-04 09:46:33 +0800
committerHe Zhenxing <zhenxing.he@sun.com>2009-12-04 09:46:33 +0800
commit16ec25c0a8438473d2273722de37ade855615ea4 (patch)
tree09ee9cda482d9a3f2fc365bd77b66441c765d6c3 /sql/rpl_handler.cc
parentf09129c6beecb20da475b41af1bba948abf826c8 (diff)
downloadmariadb-git-16ec25c0a8438473d2273722de37ade855615ea4.tar.gz
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.
Diffstat (limited to 'sql/rpl_handler.cc')
-rw-r--r--sql/rpl_handler.cc35
1 files changed, 30 insertions, 5 deletions
diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc
index da7aade5b99..c4b55e3d068 100644
--- a/sql/rpl_handler.cc
+++ b/sql/rpl_handler.cc
@@ -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)