mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Make killing of threads safer
This commit is contained in:
@ -46712,6 +46712,9 @@ not yet 100% confident in this code.
|
|||||||
@appendixsubsec Changes in release 3.23.42
|
@appendixsubsec Changes in release 3.23.42
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
|
Fixed rare hang when doing @code{mysqladmin shutdown} when there was
|
||||||
|
a lot of activity in other threads.
|
||||||
|
@item
|
||||||
Fixed problem with @code{INSERT DELAYED} where delay thread could be
|
Fixed problem with @code{INSERT DELAYED} where delay thread could be
|
||||||
hanging on @code{upgrading locks} without any apparent reasons.
|
hanging on @code{upgrading locks} without any apparent reasons.
|
||||||
@item
|
@item
|
||||||
|
@ -575,12 +575,14 @@ extern int pthread_dummy(int);
|
|||||||
struct st_my_thread_var
|
struct st_my_thread_var
|
||||||
{
|
{
|
||||||
int thr_errno;
|
int thr_errno;
|
||||||
pthread_cond_t suspend, *current_cond;
|
pthread_cond_t suspend;
|
||||||
pthread_mutex_t mutex, *current_mutex;
|
pthread_mutex_t mutex;
|
||||||
|
pthread_mutex_t * volatile current_mutex;
|
||||||
|
pthread_cond_t * volatile current_cond;
|
||||||
pthread_t pthread_self;
|
pthread_t pthread_self;
|
||||||
long id;
|
long id;
|
||||||
int cmp_length;
|
int cmp_length;
|
||||||
volatile int abort;
|
int volatile abort;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
gptr dbug;
|
gptr dbug;
|
||||||
char name[THREAD_NAME_SIZE+1];
|
char name[THREAD_NAME_SIZE+1];
|
||||||
|
@ -374,16 +374,16 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set up control struct to allow others to abort locks */
|
/* Set up control struct to allow others to abort locks */
|
||||||
pthread_mutex_lock(&thread_var->mutex);
|
|
||||||
thread_var->current_mutex= &data->lock->mutex;
|
thread_var->current_mutex= &data->lock->mutex;
|
||||||
thread_var->current_cond= cond;
|
thread_var->current_cond= cond;
|
||||||
pthread_mutex_unlock(&thread_var->mutex);
|
|
||||||
|
|
||||||
data->cond=cond;
|
data->cond=cond;
|
||||||
do
|
while (!thread_var->abort || in_wait_list)
|
||||||
{
|
{
|
||||||
pthread_cond_wait(cond,&data->lock->mutex);
|
pthread_cond_wait(cond,&data->lock->mutex);
|
||||||
} while (data->cond == cond && (!thread_var->abort || in_wait_list));
|
if (data->cond != cond)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (data->cond || data->type == TL_UNLOCK)
|
if (data->cond || data->type == TL_UNLOCK)
|
||||||
{
|
{
|
||||||
|
@ -1483,11 +1483,9 @@ longlong Item_func_get_lock::val_int()
|
|||||||
|
|
||||||
/* structure is now initialized. Try to get the lock */
|
/* structure is now initialized. Try to get the lock */
|
||||||
/* Set up control struct to allow others to abort locks */
|
/* Set up control struct to allow others to abort locks */
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
|
||||||
thd->proc_info="User lock";
|
thd->proc_info="User lock";
|
||||||
thd->mysys_var->current_mutex= &LOCK_user_locks;
|
thd->mysys_var->current_mutex= &LOCK_user_locks;
|
||||||
thd->mysys_var->current_cond= &ull->cond;
|
thd->mysys_var->current_cond= &ull->cond;
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
|
||||||
|
|
||||||
#ifdef HAVE_TIMESPEC_TS_SEC
|
#ifdef HAVE_TIMESPEC_TS_SEC
|
||||||
abstime.ts_sec=time((time_t*) 0)+(time_t) timeout;
|
abstime.ts_sec=time((time_t*) 0)+(time_t) timeout;
|
||||||
@ -1497,15 +1495,11 @@ longlong Item_func_get_lock::val_int()
|
|||||||
abstime.tv_nsec=0;
|
abstime.tv_nsec=0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while ((error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
|
while (!thd->killed &&
|
||||||
!= ETIME && error != ETIMEDOUT && ull->locked)
|
(error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
|
||||||
{
|
!= ETIME && error != ETIMEDOUT && ull->locked) ;
|
||||||
if (thd->killed || abort_loop)
|
if (thd->killed)
|
||||||
{
|
error=EINTR; // Return NULL
|
||||||
error=EINTR; // Return NULL
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ull->locked)
|
if (ull->locked)
|
||||||
{
|
{
|
||||||
if (!--ull->count)
|
if (!--ull->count)
|
||||||
|
@ -65,11 +65,9 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
|
||||||
thd->mysys_var->current_mutex= &LOCK_open;
|
thd->mysys_var->current_mutex= &LOCK_open;
|
||||||
thd->mysys_var->current_cond= &COND_refresh;
|
thd->mysys_var->current_cond= &COND_refresh;
|
||||||
thd->proc_info="Waiting for table";
|
thd->proc_info="Waiting for table";
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
|
||||||
|
|
||||||
while (global_read_lock && ! thd->killed &&
|
while (global_read_lock && ! thd->killed &&
|
||||||
thd->version == refresh_version)
|
thd->version == refresh_version)
|
||||||
|
@ -358,11 +358,9 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
|||||||
*/
|
*/
|
||||||
if (!tables)
|
if (!tables)
|
||||||
kill_delayed_threads();
|
kill_delayed_threads();
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
|
||||||
thd->mysys_var->current_mutex= &LOCK_open;
|
thd->mysys_var->current_mutex= &LOCK_open;
|
||||||
thd->mysys_var->current_cond= &COND_refresh;
|
thd->mysys_var->current_cond= &COND_refresh;
|
||||||
thd->proc_info="Flushing tables";
|
thd->proc_info="Flushing tables";
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
|
||||||
|
|
||||||
close_old_data_files(thd,thd->open_tables,1,1);
|
close_old_data_files(thd,thd->open_tables,1,1);
|
||||||
bool found=1;
|
bool found=1;
|
||||||
@ -667,13 +665,12 @@ void wait_for_refresh(THD *thd)
|
|||||||
{
|
{
|
||||||
/* Wait until the current table is up to date */
|
/* Wait until the current table is up to date */
|
||||||
const char *proc_info;
|
const char *proc_info;
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
|
||||||
thd->mysys_var->current_mutex= &LOCK_open;
|
thd->mysys_var->current_mutex= &LOCK_open;
|
||||||
thd->mysys_var->current_cond= &COND_refresh;
|
thd->mysys_var->current_cond= &COND_refresh;
|
||||||
proc_info=thd->proc_info;
|
proc_info=thd->proc_info;
|
||||||
thd->proc_info="Waiting for table";
|
thd->proc_info="Waiting for table";
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
if (!thd->killed)
|
||||||
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
||||||
|
|
||||||
pthread_mutex_unlock(&LOCK_open); // Must be unlocked first
|
pthread_mutex_unlock(&LOCK_open); // Must be unlocked first
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||||
@ -2182,7 +2179,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
|
|||||||
{
|
{
|
||||||
in_use->killed=1;
|
in_use->killed=1;
|
||||||
pthread_mutex_lock(&in_use->mysys_var->mutex);
|
pthread_mutex_lock(&in_use->mysys_var->mutex);
|
||||||
if (in_use->mysys_var->current_mutex)
|
if (in_use->mysys_var->current_cond)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(in_use->mysys_var->current_mutex);
|
pthread_mutex_lock(in_use->mysys_var->current_mutex);
|
||||||
pthread_cond_broadcast(in_use->mysys_var->current_cond);
|
pthread_cond_broadcast(in_use->mysys_var->current_cond);
|
||||||
|
@ -326,11 +326,9 @@ public:
|
|||||||
const char* msg)
|
const char* msg)
|
||||||
{
|
{
|
||||||
const char* old_msg = proc_info;
|
const char* old_msg = proc_info;
|
||||||
pthread_mutex_lock(&mysys_var->mutex);
|
|
||||||
mysys_var->current_mutex = mutex;
|
mysys_var->current_mutex = mutex;
|
||||||
mysys_var->current_cond = cond;
|
mysys_var->current_cond = cond;
|
||||||
proc_info = msg;
|
proc_info = msg;
|
||||||
pthread_mutex_unlock(&mysys_var->mutex);
|
|
||||||
return old_msg;
|
return old_msg;
|
||||||
}
|
}
|
||||||
inline void exit_cond(const char* old_msg)
|
inline void exit_cond(const char* old_msg)
|
||||||
|
@ -482,7 +482,7 @@ public:
|
|||||||
COPY_INFO info;
|
COPY_INFO info;
|
||||||
I_List<delayed_row> rows;
|
I_List<delayed_row> rows;
|
||||||
uint group_count;
|
uint group_count;
|
||||||
TABLE_LIST *table_list; // Argument
|
TABLE_LIST table_list; // Argument
|
||||||
|
|
||||||
delayed_insert()
|
delayed_insert()
|
||||||
:locks_in_memory(0),
|
:locks_in_memory(0),
|
||||||
@ -611,7 +611,9 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
|
|||||||
pthread_mutex_unlock(&LOCK_delayed_create);
|
pthread_mutex_unlock(&LOCK_delayed_create);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
tmp->table_list=table_list; // Needed to open table
|
tmp->table_list= *table_list; // Needed to open table
|
||||||
|
tmp->table_list.db= tmp->thd.db;
|
||||||
|
tmp->table_list.name= tmp->table_list.real_name=tmp->thd.query;
|
||||||
tmp->lock();
|
tmp->lock();
|
||||||
pthread_mutex_lock(&tmp->mutex);
|
pthread_mutex_lock(&tmp->mutex);
|
||||||
if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib,
|
if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib,
|
||||||
@ -846,11 +848,9 @@ void kill_delayed_threads(void)
|
|||||||
pthread_mutex_lock(&tmp->thd.mysys_var->mutex);
|
pthread_mutex_lock(&tmp->thd.mysys_var->mutex);
|
||||||
if (tmp->thd.mysys_var->current_cond)
|
if (tmp->thd.mysys_var->current_cond)
|
||||||
{
|
{
|
||||||
if (&tmp->mutex != tmp->thd.mysys_var->current_mutex)
|
pthread_mutex_lock(tmp->thd.mysys_var->current_mutex);
|
||||||
pthread_mutex_lock(tmp->thd.mysys_var->current_mutex);
|
|
||||||
pthread_cond_broadcast(tmp->thd.mysys_var->current_cond);
|
pthread_cond_broadcast(tmp->thd.mysys_var->current_cond);
|
||||||
if (&tmp->mutex != tmp->thd.mysys_var->current_mutex)
|
pthread_mutex_unlock(tmp->thd.mysys_var->current_mutex);
|
||||||
pthread_mutex_unlock(tmp->thd.mysys_var->current_mutex);
|
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&tmp->thd.mysys_var->mutex);
|
pthread_mutex_unlock(&tmp->thd.mysys_var->mutex);
|
||||||
}
|
}
|
||||||
@ -875,6 +875,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
|
|||||||
thd->thread_id=thread_id++;
|
thd->thread_id=thread_id++;
|
||||||
thd->end_time();
|
thd->end_time();
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
|
thd->killed=abort_loop;
|
||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
pthread_mutex_lock(&di->mutex);
|
pthread_mutex_lock(&di->mutex);
|
||||||
@ -905,7 +906,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
|
|||||||
|
|
||||||
/* open table */
|
/* open table */
|
||||||
|
|
||||||
if (!(di->table=open_ltable(thd,di->table_list,TL_WRITE_DELAYED)))
|
if (!(di->table=open_ltable(thd,&di->table_list,TL_WRITE_DELAYED)))
|
||||||
{
|
{
|
||||||
thd->fatal_error=1; // Abort waiting inserts
|
thd->fatal_error=1; // Abort waiting inserts
|
||||||
goto end;
|
goto end;
|
||||||
@ -913,7 +914,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
|
|||||||
if (di->table->file->has_transactions())
|
if (di->table->file->has_transactions())
|
||||||
{
|
{
|
||||||
thd->fatal_error=1;
|
thd->fatal_error=1;
|
||||||
my_error(ER_ILLEGAL_HA, MYF(0), di->table_list->real_name);
|
my_error(ER_ILLEGAL_HA, MYF(0), di->table_list.real_name);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
di->table->copy_blobs=1;
|
di->table->copy_blobs=1;
|
||||||
@ -965,10 +966,8 @@ static pthread_handler_decl(handle_delayed_insert,arg)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Information for pthread_kill */
|
/* Information for pthread_kill */
|
||||||
pthread_mutex_lock(&di->thd.mysys_var->mutex);
|
|
||||||
di->thd.mysys_var->current_mutex= &di->mutex;
|
di->thd.mysys_var->current_mutex= &di->mutex;
|
||||||
di->thd.mysys_var->current_cond= &di->cond;
|
di->thd.mysys_var->current_cond= &di->cond;
|
||||||
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
|
|
||||||
di->thd.proc_info=0;
|
di->thd.proc_info=0;
|
||||||
|
|
||||||
DBUG_PRINT("info",("Waiting for someone to insert rows"));
|
DBUG_PRINT("info",("Waiting for someone to insert rows"));
|
||||||
@ -996,10 +995,13 @@ static pthread_handler_decl(handle_delayed_insert,arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* We can't lock di->mutex and mysys_var->mutex at the same time */
|
||||||
|
pthread_mutex_unlock(&di->mutex);
|
||||||
pthread_mutex_lock(&di->thd.mysys_var->mutex);
|
pthread_mutex_lock(&di->thd.mysys_var->mutex);
|
||||||
di->thd.mysys_var->current_mutex= 0;
|
di->thd.mysys_var->current_mutex= 0;
|
||||||
di->thd.mysys_var->current_cond= 0;
|
di->thd.mysys_var->current_cond= 0;
|
||||||
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
|
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
|
||||||
|
pthread_mutex_lock(&di->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (di->tables_in_use && ! thd->lock)
|
if (di->tables_in_use && ! thd->lock)
|
||||||
|
@ -414,12 +414,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
|
|||||||
log.error=0;
|
log.error=0;
|
||||||
|
|
||||||
// tell the kill thread how to wake us up
|
// tell the kill thread how to wake us up
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
|
||||||
thd->mysys_var->current_mutex = log_lock;
|
thd->mysys_var->current_mutex = log_lock;
|
||||||
thd->mysys_var->current_cond = &COND_binlog_update;
|
thd->mysys_var->current_cond = &COND_binlog_update;
|
||||||
const char* proc_info = thd->proc_info;
|
const char* proc_info = thd->proc_info;
|
||||||
thd->proc_info = "Slave connection: waiting for binlog update";
|
thd->proc_info = "Slave connection: waiting for binlog update";
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
|
||||||
|
|
||||||
bool read_packet = 0, fatal_error = 0;
|
bool read_packet = 0, fatal_error = 0;
|
||||||
|
|
||||||
@ -444,7 +442,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags)
|
|||||||
break;
|
break;
|
||||||
case LOG_READ_EOF:
|
case LOG_READ_EOF:
|
||||||
DBUG_PRINT("wait",("waiting for data on binary log"));
|
DBUG_PRINT("wait",("waiting for data on binary log"));
|
||||||
pthread_cond_wait(&COND_binlog_update, log_lock);
|
if (!thd->killed)
|
||||||
|
pthread_cond_wait(&COND_binlog_update, log_lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -694,9 +693,9 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
|
|||||||
|
|
||||||
thr_alarm_kill(tmp->real_id);
|
thr_alarm_kill(tmp->real_id);
|
||||||
tmp->killed = 1;
|
tmp->killed = 1;
|
||||||
pthread_mutex_lock(&tmp->mysys_var->mutex);
|
|
||||||
tmp->mysys_var->abort = 1;
|
tmp->mysys_var->abort = 1;
|
||||||
if(tmp->mysys_var->current_mutex)
|
pthread_mutex_lock(&tmp->mysys_var->mutex);
|
||||||
|
if(tmp->mysys_var->current_cond)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(tmp->mysys_var->current_mutex);
|
pthread_mutex_lock(tmp->mysys_var->current_mutex);
|
||||||
pthread_cond_broadcast(tmp->mysys_var->current_cond);
|
pthread_cond_broadcast(tmp->mysys_var->current_cond);
|
||||||
|
@ -53,11 +53,9 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
|
|||||||
|
|
||||||
/* mark for close and remove all cached entries */
|
/* mark for close and remove all cached entries */
|
||||||
|
|
||||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
|
||||||
thd->mysys_var->current_mutex= &LOCK_open;
|
thd->mysys_var->current_mutex= &LOCK_open;
|
||||||
thd->mysys_var->current_cond= &COND_refresh;
|
thd->mysys_var->current_cond= &COND_refresh;
|
||||||
VOID(pthread_mutex_lock(&LOCK_open));
|
VOID(pthread_mutex_lock(&LOCK_open));
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
|
||||||
|
|
||||||
if (global_read_lock)
|
if (global_read_lock)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user