Commit d42e4d27 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Merge work:/home/bk/mysql into hundin.mysql.fi:/my/bk/mysql

parents 7288e307 7f4aee1c
......@@ -7252,7 +7252,7 @@ MySQL. How well a certain platform is suited for a high-load
mission critical MySQL server is determined by the following
factors:
@itemize
@itemize @bullet
@item
General stability of the thread library. A platform may have excellent
reputation otherwise, but if the thread library is unstable in the code
......@@ -7384,7 +7384,7 @@ If you want to configure @code{mysqld} with some extra features that are
NOT in the standard binary distributions. Here is a list of the most
common extra options that you may want to use:
@itemize
@itemize @bullet
@item @code{--with-berkeley-db}
@item @code{--with-innodb}
@item @code{--with-raid}
......@@ -23950,7 +23950,7 @@ to it clean up.
You should start by creating a wrapper library
/module with the following functions:
@itemize
@itemize @bullet
@item
@code{safe_writer_connect()}
@item
......@@ -26902,7 +26902,7 @@ flag again, the @code{SQL_MAX_JOIN_SIZE} variable will be ignored.
You can set a default value for this variable by starting @code{mysqld} with
@code{-O max_join_size=#}.
@item SQL_SAFE_MODE = 0 | 1
@item SQL_SAFE_UPDATES = 0 | 1
If set to @code{1}, MySQL will abort if an @code{UPDATE} or
@code{DELETE} is attempted that doesn't use a key or @code{LIMIT} in the
@code{WHERE} clause. This makes it possible to catch wrong updates
......@@ -34893,7 +34893,7 @@ effectiveness. Modifying the default behavior will, in most cases,
only make the search results worse. Do not alter the MySQL sources
unless you know what you are doing!
@itemize
@itemize @bullet
@item
Minimal length of word to be indexed is defined in
......@@ -42849,7 +42849,7 @@ Unfortunately, we have not yet written full documentation for it - we plan to
do this shortly. You can, however, look at our current test cases and use
them as an example. The following points should help you get started:
@itemize
@itemize @bullet
@item
The tests are located in @code{mysql-test/t/*.test}
......@@ -46712,6 +46712,12 @@ 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
Fixed problem with @code{myisampack} and @code{BLOB}.
@item
Fixes problem when one edited @code{.MRG} tables by hand.
......@@ -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];
......
......@@ -115,7 +115,7 @@ my_bool init_thr_lock()
static uint found_errors=0;
static int check_lock(struct st_lock_list *list, const char* lock_type,
const char *where, my_bool same_thread)
const char *where, my_bool same_thread, bool no_cond)
{
THR_LOCK_DATA *data,**prev;
uint count=0;
......@@ -148,6 +148,13 @@ static int check_lock(struct st_lock_list *list, const char* lock_type,
lock_type,where);
return 1;
}
if (no_cond && data->cond)
{
fprintf(stderr,
"Warning: Found active lock with not reset cond %s: %s\n",
lock_type,where);
return 1;
}
prev= &data->next;
}
if (data)
......@@ -172,10 +179,10 @@ static void check_locks(THR_LOCK *lock, const char *where,
uint old_found_errors=found_errors;
if (found_errors < MAX_FOUND_ERRORS)
{
if (check_lock(&lock->write,"write",where,1) |
check_lock(&lock->write_wait,"write_wait",where,0) |
check_lock(&lock->read,"read",where,0) |
check_lock(&lock->read_wait,"read_wait",where,0))
if (check_lock(&lock->write,"write",where,1,1) |
check_lock(&lock->write_wait,"write_wait",where,0,0) |
check_lock(&lock->read,"read",where,0,1) |
check_lock(&lock->read_wait,"read_wait",where,0,0))
found_errors++;
if (found_errors < MAX_FOUND_ERRORS)
......@@ -326,6 +333,7 @@ void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param)
data->thread=pthread_self();
data->thread_id=my_thread_id(); /* for debugging */
data->status_param=param;
data->cond=0;
}
......@@ -366,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)
{
......@@ -416,6 +424,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
DBUG_ENTER("thr_lock");
data->next=0;
data->cond=0; /* safety */
data->type=lock_type;
data->thread=pthread_self(); /* Must be reset ! */
data->thread_id=my_thread_id(); /* Must be reset ! */
......@@ -977,6 +986,10 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
lock->write_wait.data=data;
check_locks(lock,"upgrading lock",0);
}
else
{
check_locks(lock,"waiting for lock",0);
}
DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1));
}
......
......@@ -1500,11 +1500,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;
......@@ -1514,15 +1512,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)
......
......@@ -509,12 +509,14 @@ static void close_connections(void)
if (tmp->mysys_var)
{
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);
pthread_mutex_unlock(tmp->mysys_var->current_mutex);
}
pthread_mutex_unlock(&tmp->mysys_var->mutex);
}
}
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
......
......@@ -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);
......
......@@ -226,12 +226,12 @@ void THD::prepare_to_die()
pthread_mutex_lock(&mysys_var->mutex);
if (!system_thread) // Don't abort locks
mysys_var->abort=1;
if (mysys_var->current_mutex)
{
pthread_mutex_lock(mysys_var->current_mutex);
pthread_cond_broadcast(mysys_var->current_cond);
pthread_mutex_unlock(mysys_var->current_mutex);
}
if (mysys_var->current_cond)
{
pthread_mutex_lock(mysys_var->current_mutex);
pthread_cond_broadcast(mysys_var->current_cond);
pthread_mutex_unlock(mysys_var->current_mutex);
}
pthread_mutex_unlock(&mysys_var->mutex);
}
}
......
......@@ -326,11 +326,9 @@ class THD :public ilink {
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 @@ class delayed_insert :public ilink {
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),
......@@ -511,10 +511,12 @@ class delayed_insert :public ilink {
delayed_row *row;
while ((row=rows.get()))
delete row;
pthread_mutex_destroy(&mutex);
if (table)
close_thread_tables(&thd);
VOID(pthread_mutex_lock(&LOCK_thread_count));
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_cond_destroy(&cond_client);
thd.unlink(); // Must be unlinked under lock
x_free(thd.query);
thd.user=thd.host=0;
......@@ -609,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,
......@@ -842,13 +846,11 @@ void kill_delayed_threads(void)
if (tmp->thd.mysys_var)
{
pthread_mutex_lock(&tmp->thd.mysys_var->mutex);
if (tmp->thd.mysys_var->current_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);
}
......@@ -873,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);
......@@ -903,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;
......@@ -911,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;
......@@ -963,14 +966,12 @@ 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"));
for ( ; ;)
while (!thd->killed)
{
int error;
#if (defined(HAVE_BROKEN_COND_TIMEDWAIT) || defined(HAVE_LINUXTHREADS))
......@@ -994,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