Commit 346557a9 authored by unknown's avatar unknown

Don't abort if we call my_thread_end() multiple times

Fixed new introduced bug in my_time.c


BitKeeper/deleted/.del-valgrind.supp.orig:
  Delete: mysql-test/valgrind.supp.orig
mysys/my_thr_init.c:
  More comments
  Don't abort if we call my_thread_end() multiple times
sql-common/my_time.c:
  Fixed wrong patch in last commit
sql/sql_cache.cc:
  Fixed old bad merge (not critical)
sql/tztime.cc:
  Portability fix
parent d2e04479
#
# Suppress some common (not fatal) errors in system libraries found by valgrind
#
#
# Pthread doesn't free all thread specific memory before program exists
#
{
pthread allocate_tls memory loss
Memcheck:Leak
fun:calloc
fun:_dl_allocate_tls
fun:allocate_stack
fun:pthread_create@@GLIBC_2.1
}
{
pthread allocate_dtv memory loss
Memcheck:Leak
fun:calloc
fun:allocate_dtv
fun:_dl_allocate_tls_storage
fun:__GI__dl_allocate_tls
fun:pthread_create
}
{
pthread allocate_dtv memory loss second
Memcheck:Leak
fun:calloc
fun:allocate_dtv
fun:_dl_allocate_tls
fun:pthread_create*
}
{
pthread allocate_dtv memory loss second
Memcheck:Leak
fun:calloc
fun:allocate_dtv
fun:_dl_allocate_tls
fun:pthread_create*
}
{
pthread memalign memory loss
Memcheck:Leak
fun:memalign
fun:_dl_allocate_tls_storage
fun:__GI__dl_allocate_tls
fun:pthread_create
}
{
pthread pthread_key_create
Memcheck:Leak
fun:malloc
fun:*
fun:*
fun:pthread_key_create
fun:my_thread_global_init
}
{
pthread strstr uninit
Memcheck:Cond
fun:strstr
obj:/lib/tls/libpthread.so.*
obj:/lib/tls/libpthread.so.*
fun:call_init
fun:_dl_init
obj:/lib/ld-*.so
}
{
pthread strstr uninit
Memcheck:Cond
fun:strstr
obj:/lib/tls/libpthread.so.*
obj:/lib/tls/libpthread.so.*
fun:call_init
fun:_dl_init
obj:/lib/ld-*.so
}
{
pthread errno
Memcheck:Leak
fun:calloc
fun:_dlerror_run
fun:dlsym
fun:__errno_location
}
#
# Warnings in libz becasue it works with aligned memory(?)
#
{
libz tr_flush_block
Memcheck:Cond
fun:_tr_flush_block
fun:deflate_slow
fun:deflate
fun:do_flush
fun:gzclose
}
{
libz tr_flush_block2
Memcheck:Cond
fun:_tr_flush_block
fun:deflate_slow
fun:deflate
fun:compress2
}
{
libz longest_match
Memcheck:Cond
fun:longest_match
fun:deflate_slow
fun:deflate
fun:do_flush
}
{
libz longest_match2
Memcheck:Cond
fun:longest_match
fun:deflate_slow
fun:deflate
fun:compress2
}
{
libz deflate
Memcheck:Cond
obj:*/libz.so.*
obj:*/libz.so.*
fun:deflate
fun:compress2
}
{
libz deflate2
Memcheck:Cond
obj:*/libz.so.*
obj:*/libz.so.*
fun:deflate
obj:*/libz.so.*
fun:gzflush
}
{
libz deflate3
Memcheck:Cond
obj:*/libz.so.*
obj:*/libz.so.*
fun:deflate
fun:do_flush
}
#
# Warning from my_thread_init becasue mysqld dies before kill thread exists
#
{
my_thread_init kill thread memory loss second
Memcheck:Leak
fun:calloc
fun:my_thread_init
fun:kill_server_thread
}
#
# Warning when printing stack trace (to suppress some not needed warnings)
#
{
vprintf on stacktrace
Memcheck:Cond
fun:vfprintf
fun:uffered_vfprintf
fun:vfprintf
fun:fprintf
fun:print_stacktrace
}
...@@ -120,20 +120,22 @@ my_bool my_thread_global_init(void) ...@@ -120,20 +120,22 @@ my_bool my_thread_global_init(void)
void my_thread_global_end(void) void my_thread_global_end(void)
{ {
struct timespec abstime; struct timespec abstime;
set_timespec(abstime, my_thread_end_wait_time);
my_bool all_threads_killed= 1; my_bool all_threads_killed= 1;
set_timespec(abstime, my_thread_end_wait_time);
pthread_mutex_lock(&THR_LOCK_threads); pthread_mutex_lock(&THR_LOCK_threads);
while (THR_thread_count) while (THR_thread_count > 0)
{ {
int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
&abstime); &abstime);
if (error == ETIMEDOUT || error == ETIME) if (error == ETIMEDOUT || error == ETIME)
{ {
if (THR_thread_count) if (THR_thread_count)
fprintf(stderr,"error in my_thread_global_end(): %d threads didn't exit\n", fprintf(stderr,
"Error in my_thread_global_end(): %d threads didn't exit\n",
THR_thread_count); THR_thread_count);
all_threads_killed= 0; all_threads_killed= 0;
break;
} }
} }
pthread_mutex_unlock(&THR_LOCK_threads); pthread_mutex_unlock(&THR_LOCK_threads);
...@@ -169,10 +171,23 @@ void my_thread_global_end(void) ...@@ -169,10 +171,23 @@ void my_thread_global_end(void)
static long thread_id=0; static long thread_id=0;
/* /*
We can't use mutex_locks here if we are using windows as Allocate thread specific memory for the thread, used by mysys and dbug
we may have compiled the program with SAFE_MUTEX, in which
case the checking of mutex_locks will not work until SYNOPSIS
the pthread_self thread specific variable is initialized. my_thread_init()
NOTES
We can't use mutex_locks here if we are using windows as
we may have compiled the program with SAFE_MUTEX, in which
case the checking of mutex_locks will not work until
the pthread_self thread specific variable is initialized.
This function may called multiple times for a thread, for example
if one uses my_init() followed by mysql_server_init().
RETURN
0 ok
1 Fatal error; mysys/dbug functions can't be used
*/ */
my_bool my_thread_init(void) my_bool my_thread_init(void)
...@@ -224,14 +239,26 @@ my_bool my_thread_init(void) ...@@ -224,14 +239,26 @@ my_bool my_thread_init(void)
} }
/*
Deallocate memory used by the thread for book-keeping
SYNOPSIS
my_thread_end()
NOTE
This may be called multiple times for a thread.
This happens for example when one calls 'mysql_server_init()'
mysql_server_end() and then ends with a mysql_end().
*/
void my_thread_end(void) void my_thread_end(void)
{ {
struct st_my_thread_var *tmp; struct st_my_thread_var *tmp;
tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
#ifdef EXTRA_DEBUG_THREADS #ifdef EXTRA_DEBUG_THREADS
fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n", fprintf(stderr,"my_thread_end(): tmp: 0x%lx thread_id=%ld\n",
tmp,pthread_self()); (long) tmp, pthread_self());
#endif #endif
if (tmp && tmp->init) if (tmp && tmp->init)
{ {
...@@ -253,15 +280,23 @@ void my_thread_end(void) ...@@ -253,15 +280,23 @@ void my_thread_end(void)
#else #else
tmp->init= 0; tmp->init= 0;
#endif #endif
/*
Decrement counter for number of running threads. We are using this
in my_thread_global_end() to wait until all threads have called
my_thread_end and thus freed all memory they have allocated in
my_thread_init() and DBUG_xxxx
*/
pthread_mutex_lock(&THR_LOCK_threads);
DBUG_ASSERT(THR_thread_count != 0);
if (--THR_thread_count == 0)
pthread_cond_signal(&THR_COND_threads);
pthread_mutex_unlock(&THR_LOCK_threads);
} }
/* The following free has to be done, even if my_thread_var() is 0 */ /* The following free has to be done, even if my_thread_var() is 0 */
#if !defined(__WIN__) || defined(USE_TLS) #if !defined(__WIN__) || defined(USE_TLS)
pthread_setspecific(THR_KEY_mysys,0); pthread_setspecific(THR_KEY_mysys,0);
#endif #endif
pthread_mutex_lock(&THR_LOCK_threads);
if (--THR_thread_count == 0)
pthread_cond_signal(&THR_COND_threads);
pthread_mutex_unlock(&THR_LOCK_threads);
} }
struct st_my_thread_var *_my_thread_var(void) struct st_my_thread_var *_my_thread_var(void)
......
...@@ -547,9 +547,9 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time, ...@@ -547,9 +547,9 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
{ {
/* String given as one number; assume HHMMSS format */ /* String given as one number; assume HHMMSS format */
date[0]= 0; date[0]= 0;
date[1]= ((ulong) value)/10000; date[1]= (ulong) (value/10000);
date[2]= ((ulong) value)/100 % 100; date[2]= (ulong) (value/100 % 100);
date[3]= ((ulong) value) % 100; date[3]= (ulong) (value % 100);
state=4; state=4;
goto fractional; goto fractional;
} }
......
...@@ -1039,7 +1039,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -1039,7 +1039,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
while (sql[i]=='(') while (sql[i]=='(')
i++; i++;
/* /*
Test if the query is a SELECT Test if the query is a SELECT
(pre-space is removed in dispatch_command). (pre-space is removed in dispatch_command).
...@@ -1051,7 +1050,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -1051,7 +1050,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
if ((my_toupper(system_charset_info, sql[i]) != 'S' || if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
my_toupper(system_charset_info, sql[i + 1]) != 'E' || my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
my_toupper(system_charset_info, sql[i + 2]) != 'L') && my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
sql[0] != '/') sql[i] != '/')
{ {
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err; goto err;
......
...@@ -1743,9 +1743,9 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) ...@@ -1743,9 +1743,9 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_leapcnt++; tz_leapcnt++;
DBUG_PRINT("info", DBUG_PRINT("info",
("time_zone_leap_second table: tz_leapcnt:%u tt_time: %lu offset: %ld", ("time_zone_leap_second table: tz_leapcnt: %u tt_time: %lu offset: %ld",
tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans, tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans,
tz_lsis[tz_leapcnt-1].ls_corr)); tz_lsis[tz_leapcnt-1].ls_corr));
res= table->file->index_next(table->record[0]); res= table->file->index_next(table->record[0]);
} }
......
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