mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Fixed memory loss detected on P8. This can happen when we call after_flush but never call after_rollback() or after_commit().
The old code used pthread_setspecific() to store temporary data used by the thread. This is not safe when used with thread pool, as the thread may change for the transaction. The fix is to save the data in THD, which is guaranteed to be properly freed. I also fixed the code so that we don't do a malloc() for every transaction.
This commit is contained in:
@ -38,8 +38,6 @@ typedef struct Trans_binlog_info {
|
||||
char log_file[FN_REFLEN];
|
||||
} Trans_binlog_info;
|
||||
|
||||
static pthread_key(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
|
||||
|
||||
int get_user_var_int(const char *name,
|
||||
long long int *value, int *null_value)
|
||||
{
|
||||
@ -143,13 +141,6 @@ int delegates_init()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pthread_key_create(&RPL_TRANS_BINLOG_INFO, NULL))
|
||||
{
|
||||
sql_print_error("Error while creating pthread specific data key for replication. "
|
||||
"Please report a bug.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -195,27 +186,27 @@ void delegates_destroy()
|
||||
int Trans_delegate::after_commit(THD *thd, bool all)
|
||||
{
|
||||
Trans_param param;
|
||||
Trans_binlog_info *log_info;
|
||||
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
|
||||
int ret= 0;
|
||||
|
||||
param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
|
||||
|
||||
Trans_binlog_info *log_info=
|
||||
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
|
||||
log_info= thd->semisync_info;
|
||||
|
||||
param.log_file= log_info ? log_info->log_file : 0;
|
||||
param.log_file= log_info && log_info->log_file[0] ? log_info->log_file : 0;
|
||||
param.log_pos= log_info ? log_info->log_pos : 0;
|
||||
|
||||
int ret= 0;
|
||||
FOREACH_OBSERVER(ret, after_commit, false, (¶m));
|
||||
|
||||
/*
|
||||
This is the end of a real transaction or autocommit statement, we
|
||||
can free the memory allocated for binlog file and position.
|
||||
can mark the memory unused.
|
||||
*/
|
||||
if (is_real_trans && log_info)
|
||||
{
|
||||
my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, NULL);
|
||||
my_free(log_info);
|
||||
log_info->log_file[0]= 0;
|
||||
log_info->log_pos= 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -223,27 +214,27 @@ int Trans_delegate::after_commit(THD *thd, bool all)
|
||||
int Trans_delegate::after_rollback(THD *thd, bool all)
|
||||
{
|
||||
Trans_param param;
|
||||
Trans_binlog_info *log_info;
|
||||
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
|
||||
int ret= 0;
|
||||
|
||||
param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
|
||||
|
||||
Trans_binlog_info *log_info=
|
||||
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
|
||||
|
||||
param.log_file= log_info ? log_info->log_file : 0;
|
||||
log_info= thd->semisync_info;
|
||||
|
||||
param.log_file= log_info && log_info->log_file[0] ? log_info->log_file : 0;
|
||||
param.log_pos= log_info ? log_info->log_pos : 0;
|
||||
|
||||
int ret= 0;
|
||||
FOREACH_OBSERVER(ret, after_rollback, false, (¶m));
|
||||
|
||||
/*
|
||||
This is the end of a real transaction or autocommit statement, we
|
||||
can free the memory allocated for binlog file and position.
|
||||
can mark the memory unused.
|
||||
*/
|
||||
if (is_real_trans && log_info)
|
||||
{
|
||||
my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, NULL);
|
||||
my_free(log_info);
|
||||
log_info->log_file[0]= 0;
|
||||
log_info->log_pos= 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -254,25 +245,24 @@ int Binlog_storage_delegate::after_flush(THD *thd,
|
||||
bool synced)
|
||||
{
|
||||
Binlog_storage_param param;
|
||||
Trans_binlog_info *log_info;
|
||||
uint32 flags=0;
|
||||
int ret= 0;
|
||||
|
||||
if (synced)
|
||||
flags |= BINLOG_STORAGE_IS_SYNCED;
|
||||
|
||||
Trans_binlog_info *log_info=
|
||||
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
|
||||
|
||||
if (!log_info)
|
||||
if (!(log_info= thd->semisync_info))
|
||||
{
|
||||
if(!(log_info=
|
||||
(Trans_binlog_info *)my_malloc(sizeof(Trans_binlog_info), MYF(0))))
|
||||
(Trans_binlog_info*) my_malloc(sizeof(Trans_binlog_info), MYF(0))))
|
||||
return 1;
|
||||
my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, log_info);
|
||||
thd->semisync_info= log_info;
|
||||
}
|
||||
|
||||
|
||||
strcpy(log_info->log_file, log_file+dirname_length(log_file));
|
||||
log_info->log_pos = log_pos;
|
||||
|
||||
int ret= 0;
|
||||
FOREACH_OBSERVER(ret, after_flush, false,
|
||||
(¶m, log_info->log_file, log_info->log_pos, flags));
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user