Commit 9591abbd authored by unknown's avatar unknown

Make killing of threads safer


Docs/manual.texi:
  Changelog
sql/sql_insert.cc:
  Fix problem with INSERT DELAYED during shutdown
parent 42959176
......@@ -46712,6 +46712,9 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.42
@itemize @bullet
@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
hanging on @code{upgrading locks} without any apparent reasons.
@item
......@@ -575,12 +575,14 @@ extern int pthread_dummy(int);
struct st_my_thread_var
{
int thr_errno;
pthread_cond_t suspend, *current_cond;
pthread_mutex_t mutex, *current_mutex;
pthread_cond_t suspend;
pthread_mutex_t mutex;
pthread_mutex_t * volatile current_mutex;
pthread_cond_t * volatile current_cond;
pthread_t pthread_self;
long id;
int cmp_length;
volatile int abort;
int volatile abort;
#ifndef DBUG_OFF
gptr dbug;
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 */
pthread_mutex_lock(&thread_var->mutex);
thread_var->current_mutex= &data->lock->mutex;
thread_var->current_cond= cond;
pthread_mutex_unlock(&thread_var->mutex);
data->cond=cond;
do
while (!thread_var->abort || in_wait_list)
{
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)
{
......
......@@ -1483,11 +1483,9 @@ longlong Item_func_get_lock::val_int()
/* structure is now initialized. Try to get the lock */
/* Set up control struct to allow others to abort locks */
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->proc_info="User lock";
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
pthread_mutex_unlock(&thd->mysys_var->mutex);
#ifdef HAVE_TIMESPEC_TS_SEC
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;
#endif
while ((error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
!= ETIME && error != ETIMEDOUT && ull->locked)
{
if (thd->killed || abort_loop)
{
error=EINTR; // Return NULL
break;
}
}
while (!thd->killed &&
(error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
!= ETIME && error != ETIMEDOUT && ull->locked) ;
if (thd->killed)
error=EINTR; // Return NULL
if (ull->locked)
{
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(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Waiting for table";
pthread_mutex_unlock(&thd->mysys_var->mutex);
while (global_read_lock && ! thd->killed &&
thd->version == refresh_version)
......
......@@ -358,11 +358,9 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
*/
if (!tables)
kill_delayed_threads();
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
pthread_mutex_unlock(&thd->mysys_var->mutex);
close_old_data_files(thd,thd->open_tables,1,1);
bool found=1;
......@@ -667,13 +665,12 @@ void wait_for_refresh(THD *thd)
{
/* Wait until the current table is up to date */
const char *proc_info;
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
proc_info=thd->proc_info;
thd->proc_info="Waiting for table";
pthread_mutex_unlock(&thd->mysys_var->mutex);
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
if (!thd->killed)
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
pthread_mutex_unlock(&LOCK_open); // Must be unlocked first
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;
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_cond_broadcast(in_use->mysys_var->current_cond);
......
......@@ -326,11 +326,9 @@ public:
const char* msg)
{
const char* old_msg = proc_info;
pthread_mutex_lock(&mysys_var->mutex);
mysys_var->current_mutex = mutex;
mysys_var->current_cond = cond;
proc_info = msg;
pthread_mutex_unlock(&mysys_var->mutex);
return old_msg;
}
inline void exit_cond(const char* old_msg)
......
......@@ -482,7 +482,7 @@ public:
COPY_INFO info;
I_List<delayed_row> rows;
uint group_count;
TABLE_LIST *table_list; // Argument
TABLE_LIST table_list; // Argument
delayed_insert()
: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);
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();
pthread_mutex_lock(&tmp->mutex);
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);
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);
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);
}
......@@ -875,6 +875,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
thd->thread_id=thread_id++;
thd->end_time();
threads.append(thd);
thd->killed=abort_loop;
pthread_mutex_unlock(&LOCK_thread_count);
pthread_mutex_lock(&di->mutex);
......@@ -905,7 +906,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
/* 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
goto end;
......@@ -913,7 +914,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
if (di->table->file->has_transactions())
{
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;
}
di->table->copy_blobs=1;
......@@ -965,10 +966,8 @@ static pthread_handler_decl(handle_delayed_insert,arg)
#endif
/* 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_cond= &di->cond;
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
di->thd.proc_info=0;
DBUG_PRINT("info",("Waiting for someone to insert rows"));
......@@ -996,10 +995,13 @@ static pthread_handler_decl(handle_delayed_insert,arg)
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);
di->thd.mysys_var->current_mutex= 0;
di->thd.mysys_var->current_cond= 0;
pthread_mutex_unlock(&di->thd.mysys_var->mutex);
pthread_mutex_lock(&di->mutex);
}
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;
// 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_cond = &COND_binlog_update;
const char* proc_info = thd->proc_info;
thd->proc_info = "Slave connection: waiting for binlog update";
pthread_mutex_unlock(&thd->mysys_var->mutex);
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;
case LOG_READ_EOF:
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;
default:
......@@ -694,9 +693,9 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
thr_alarm_kill(tmp->real_id);
tmp->killed = 1;
pthread_mutex_lock(&tmp->mysys_var->mutex);
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_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 */
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
pthread_mutex_unlock(&thd->mysys_var->mutex);
if (global_read_lock)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment