From 454c763c6be44b34c8e1ff9b8561ab21e717b742 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 22 Jan 2007 02:32:07 +0200 Subject: [PATCH 1/9] Fix for configure to detect library correctly. Fix to check library in use during runtime. Fix for Bug#16995, "idle connections not being killed due to timeout when NPTL is used". BUILD/SETUP.sh: To avoid warnings during compilation. configure.in: Fixed configure so that it can correctly detect between NPTL and Linuxthreads. include/my_global.h: Fix for Linuxthreads. include/my_pthread.h: Added defines for different libraries that can be detected. Currently only 'other', 'nptl', and 'lt' (linuxthreads) are being used. changed sigset() and signal() to my_sigset() and my_signal() include/thr_alarm.h: Removed defines for Linuxthreads. This is now detected during runtime and handled in the thr_alarm.c mysys/my_pthread.c: Runtime check for library. mysys/thr_alarm.c: Runtime checks for library and corresponding signals. sql/mysqld.cc: Added function for detecting thread library in use during start-up. THR_KILL_SIGNAL removed, setting signals during runtime. --- BUILD/SETUP.sh | 4 +- configure.in | 161 ++++++++++++++++++++++++++----------------- include/my_global.h | 7 +- include/my_pthread.h | 41 ++++++++--- include/thr_alarm.h | 5 -- mysys/my_pthread.c | 4 +- mysys/thr_alarm.c | 93 +++++++++++-------------- sql/mysqld.cc | 53 +++++++++----- 8 files changed, 216 insertions(+), 152 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 150f9e28b41..779d0f1c660 100644 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -39,8 +39,8 @@ global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wch c_warnings="$global_warnings -Wunused" cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor" -alpha_cflags="-mcpu=ev6 -Wa,-mev6" # Not used yet -pentium_cflags="-mcpu=pentiumpro" +#alpha_cflags="-mcpu=ev6 -Wa,-mev6" # Not used yet +#pentium_cflags="-mcpu=pentiumpro" sparc_cflags="" # be as fast as we can be without losing our ability to backtrace diff --git a/configure.in b/configure.in index a59f1e30ab2..10f8ca37a4b 100644 --- a/configure.in +++ b/configure.in @@ -388,15 +388,16 @@ AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") if expr "$target_os" : "[[Ll]]inux.*" > /dev/null then MYSQLD_DEFAULT_SWITCHES="--skip-locking" - IS_LINUX="true" + TARGET_LINUX="true" AC_MSG_RESULT("yes"); + AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux]) else MYSQLD_DEFAULT_SWITCHES="" - IS_LINUX="false" + TARGET_LINUX="false" AC_MSG_RESULT("no"); fi AC_SUBST(MYSQLD_DEFAULT_SWITCHES) -AC_SUBST(IS_LINUX) +AC_SUBST(TARGET_LINUX) dnl Find paths to some shell programs AC_PATH_PROG(LN, ln, ln) @@ -576,7 +577,7 @@ AC_SUBST(NOINST_LDFLAGS) # (this is true on the MySQL build machines to avoid NSS problems) # -if test "$IS_LINUX" = "true" -a "$static_nss" = "" +if test "$TARGET_LINUX" = "true" -a "$static_nss" = "" then tmp=`nm /usr/lib/libc.a | grep _nss_files_getaliasent_r` if test -n "$tmp" @@ -827,7 +828,7 @@ struct request_info *req; ]) AC_SUBST(WRAPLIBS) -if test "$IS_LINUX" = "true"; then +if test "$TARGET_LINUX" = "true"; then AC_MSG_CHECKING([for atomic operations]) AC_LANG_SAVE @@ -870,7 +871,7 @@ int main() [ USE_PSTACK=no ]) pstack_libs= pstack_dirs= - if test "$USE_PSTACK" = yes -a "$IS_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no" + if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no" then have_libiberty= have_libbfd= my_save_LIBS="$LIBS" @@ -1239,63 +1240,98 @@ with_posix_threads="no" # Hack for DEC-UNIX (OSF1) if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" then - # Look for LinuxThreads. - AC_MSG_CHECKING("LinuxThreads") - grepres=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l` - getconfres=`which getconf >/dev/null && getconf GNU_LIBPTHREAD_VERSION | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ |grep LINUXTHREADS | wc -l || echo 0` - if test "$grepres" -gt 0 -o "$getconfres" -gt 0 + AC_MSG_CHECKING("Linux threads") + if test "$TARGET_LINUX" = "true" then - AC_MSG_RESULT("Found") - AC_DEFINE(HAVE_LINUXTHREADS) - # Linux 2.0 sanity check - AC_TRY_COMPILE([#include ], [int a = sched_get_priority_min(1);], , - AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual])) - # RedHat 5.0 does not work with dynamic linking of this. -static also - # gives a speed increase in linux so it does not hurt on other systems. - with_named_thread="-lpthread" - else - AC_MSG_RESULT("Not found") - # If this is a linux machine we should barf - AC_MSG_CHECKING("NPTL") - if test "$IS_LINUX" = "true" - then - getconfres=`which getconf >/dev/null && getconf GNU_LIBPTHREAD_VERSION | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ |grep NPTL | wc -l || echo 0` - if test "$getconfres" -gt 0 + AC_MSG_RESULT("starting") + # use getconf to check glibc contents + AC_MSG_CHECKING("getconf GNU_LIBPTHREAD_VERSION") + case `getconf GNU_LIBPTHREAD_VERSION | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` in + NPTL* ) + AC_MSG_RESULT("NPTL") + AC_DEFINE([HAVE_NPTL], [1], [NPTL threads implementation]) + with_named_thread="-lpthread" + ;; + LINUXTHREADS* ) + AC_MSG_RESULT("Linuxthreads") + AC_DEFINE([HAVE_LINUXTHREADS], [1], + [Whether we are using Xavier Leroy's LinuxThreads]) + with_named_thread="-lpthread" + ;; + * ) + AC_MSG_RESULT("unknown") + ;; + esac + if test "$with_named_thread" = "no" then - AC_DEFINE(HAVE_LINUXTHREADS) dnl All this code predates NPTL, so "have linuxthreads" is a poor name. - with_named_thread="-lpthread" - else - AC_MSG_ERROR([This is a Linux system and neither Linuxthreads nor NPTL were -found. Please install Linuxthreads or a new glibc and try -again. See the Installation chapter in the Reference Manual for -more information.]) - fi - else - AC_MSG_CHECKING("DEC threads") - if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a - then - with_named_thread="-lpthread -lmach -lexc" - CFLAGS="$CFLAGS -D_REENTRANT" - CXXFLAGS="$CXXFLAGS -D_REENTRANT" - AC_DEFINE(HAVE_DEC_THREADS) - AC_MSG_RESULT("yes") - else - AC_MSG_RESULT("no") - AC_MSG_CHECKING("DEC 3.2 threads") - if test -f /usr/shlib/libpthreads.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a - then - with_named_thread="-lpthreads -lmach -lc_r" - AC_DEFINE(HAVE_DEC_THREADS) - AC_DEFINE(HAVE_DEC_3_2_THREADS) - with_osf32_threads="yes" - MYSQLD_DEFAULT_SWITCHES="--skip-thread-priority" - AC_MSG_RESULT("yes") - else - AC_MSG_RESULT("no") + # old method, check headers + # Look for LinuxThreads. + AC_MSG_CHECKING("LinuxThreads in header file comment") + res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l` + if test "$res" -gt 0 + then + AC_MSG_RESULT("Found") + AC_DEFINE([HAVE_LINUXTHREADS], [1], + [Whether we are using Xavier Leroy's LinuxThreads]) + # Linux 2.0 sanity check + AC_TRY_COMPILE([#include ], [int a = sched_get_priority_min(1);], , + AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual])) + # RedHat 5.0 does not work with dynamic linking of this. -static also + # gives a speed increase in linux so it does not hurt on other systems. + with_named_thread="-lpthread" + else + AC_MSG_RESULT("Not found") + # If this is a linux machine we should barf + AC_MSG_ERROR([This is a Linux system without a working getconf, +and Linuxthreads was not found. Please install it (or a new glibc) and try again. +See the Installation chapter in the Reference Manual for more information.]) fi - fi - fi - fi + else + AC_MSG_RESULT("no need to check headers") + fi + AC_MSG_CHECKING("for pthread_create in -lpthread"); + ac_save_LIBS="$LIBS" + LIBS="$LIBS -lpthread" + AC_TRY_LINK( [#include ], + [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ], + AC_MSG_RESULT("yes"), + [ AC_MSG_RESULT("no") + AC_MSG_ERROR([ +This is a Linux system claiming to support threads, either Linuxthreads or NPTL, but linking a test program failed. +Please install one of these (or a new glibc) and try again. +See the Installation chapter in the Reference Manual for more information.]) ] + ) + LIBS="$ac_save_LIBS" + else + AC_MSG_RESULT("no") + fi # "$TARGET_LINUX" +fi # "$with_named_thread" = "no" -a "$with_mit_threads" = "no" + +if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" +then + AC_MSG_CHECKING("DEC threads") + if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a + then + with_named_thread="-lpthread -lmach -lexc" + CFLAGS="$CFLAGS -D_REENTRANT" + CXXFLAGS="$CXXFLAGS -D_REENTRANT" + AC_DEFINE(HAVE_DEC_THREADS) + AC_MSG_RESULT("yes") + else + AC_MSG_RESULT("no") + AC_MSG_CHECKING("DEC 3.2 threads") + if test -f /usr/shlib/libpthreads.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a + then + with_named_thread="-lpthreads -lmach -lc_r" + AC_DEFINE(HAVE_DEC_THREADS) + AC_DEFINE(HAVE_DEC_3_2_THREADS) + with_osf32_threads="yes" + MYSQLD_DEFAULT_SWITCHES="--skip-thread-priority" + AC_MSG_RESULT("yes") + else + AC_MSG_RESULT("no") + fi + fi fi @@ -1720,7 +1756,7 @@ fi AC_SUBST(COMPILATION_COMMENT) AC_MSG_CHECKING("need of special linking flags") -if test "$IS_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes" +if test "$TARGET_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes" then LDFLAGS="$LDFLAGS -rdynamic" AC_MSG_RESULT("-rdynamic") @@ -1873,6 +1909,7 @@ AC_CHECK_FUNCS(alarm bmove \ tell atod memcpy memmove \ setupterm strcasecmp sighold vidattr lrand48 localtime_r \ sigset sigthreadmask pthread_sigmask pthread_setprio pthread_setprio_np \ + sigaction sigemptyset sigaddset \ pthread_setschedparam pthread_attr_setprio pthread_attr_setschedparam \ pthread_attr_create pthread_getsequence_np pthread_attr_setstacksize \ pthread_attr_getstacksize pthread_key_delete \ @@ -1884,7 +1921,7 @@ CFLAGS="$ORG_CFLAGS" # Sanity check: We chould not have any fseeko symbol unless # large_file_support=yes AC_CHECK_FUNCS(fseeko, -[if test "$large_file_support" = no -a "$IS_LINUX" = "true"; +[if test "$large_file_support" = no -a "$TARGET_LINUX" = "true"; then AC_MSG_ERROR("Found fseeko symbol but large_file_support is not enabled!"); fi] diff --git a/include/my_global.h b/include/my_global.h index 37e53c65dec..e6bf9a9b840 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -97,7 +97,7 @@ /* Fix problem with S_ISLNK() on Linux */ -#if defined(HAVE_LINUXTHREADS) +#if defined(TARGET_OS_LINUX) || defined(__GLIBC__) #undef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -348,7 +348,10 @@ int __void__; #endif /* Define some useful general macros */ -#if !defined(max) +#if defined(__cplusplus) && defined(__GNUC__) +#define max(a, b) ((a) >? (b)) +#define min(a, b) ((a) (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index 7620b46e08b..e1a7ecab4ab 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -28,6 +28,14 @@ extern "C" { #endif /* __cplusplus */ +/* Thread library */ + +#define THD_LIB_OTHER 1 +#define THD_LIB_NPTL 2 +#define THD_LIB_LT 4 + +extern uint thd_lib_detected; + #if defined(__WIN__) || defined(OS2) #ifdef OS2 @@ -286,8 +294,8 @@ extern int my_pthread_create_detached; #undef HAVE_PTHREAD_RWLOCK_RDLOCK #undef HAVE_SNPRINTF -#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) -#define signal(A,B) pthread_signal((A),(void (*)(int)) (B)) +#define my_sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) +#define my_signal(A,B) pthread_signal((A),(void (*)(int)) (B)) #define my_pthread_attr_setprio(A,B) #endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ @@ -324,14 +332,27 @@ extern int my_pthread_cond_init(pthread_cond_t *mp, #if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX) int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ #endif -#if !defined(HAVE_SIGSET) && !defined(HAVE_mit_thread) && !defined(sigset) -#define sigset(A,B) do { struct sigaction s; sigset_t set; \ - sigemptyset(&set); \ - s.sa_handler = (B); \ - s.sa_mask = set; \ - s.sa_flags = 0; \ - sigaction((A), &s, (struct sigaction *) NULL); \ + +/* + We define my_sigset() and use that instead of the system sigset() so that + we can favor an implementation based on sigaction(). On some systems, such + as Mac OS X, sigset() results in flags such as SA_RESTART being set, and + we want to make sure that no such flags are set. +*/ +#if defined(HAVE_SIGACTION) && !defined(my_sigset) +#define my_sigset(A,B) do { struct sigaction s; sigset_t set; int rc; \ + DBUG_ASSERT((A) != 0); \ + sigemptyset(&set); \ + s.sa_handler = (B); \ + s.sa_mask = set; \ + s.sa_flags = 0; \ + rc= sigaction((A), &s, (struct sigaction *) NULL); \ + DBUG_ASSERT(rc == 0); \ } while (0) +#elif defined(HAVE_SIGSET) && !defined(my_sigset) +#define my_sigset(A,B) sigset((A),(B)) +#elif !defined(my_sigset) +#define my_sigset(A,B) signal((A),(B)) #endif #ifndef my_pthread_setprio @@ -416,7 +437,7 @@ struct tm *localtime_r(const time_t *clock, struct tm *res); #undef pthread_detach_this_thread #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); } #undef sigset -#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) +#define my_sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) #endif #if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER) diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 7a10d6886ce..0c26a67acf4 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -25,11 +25,6 @@ extern "C" { #ifndef USE_ALARM_THREAD #define USE_ONE_SIGNAL_HAND /* One must call process_alarm */ #endif -#ifdef HAVE_LINUXTHREADS -#define THR_CLIENT_ALARM SIGALRM -#else -#define THR_CLIENT_ALARM SIGUSR1 -#endif #ifdef HAVE_rts_threads #undef USE_ONE_SIGNAL_HAND #define USE_ALARM_THREAD diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index a8157cc2f91..3eaf27844b2 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -31,6 +31,8 @@ #define SCHED_POLICY SCHED_OTHER #endif +uint thd_lib_detected; + #ifndef my_pthread_setprio void my_pthread_setprio(pthread_t thread_id,int prior) { @@ -320,7 +322,7 @@ void *sigwait_thread(void *set_arg) sigaction(i, &sact, (struct sigaction*) 0); } } - sigaddset(set,THR_CLIENT_ALARM); + sigaddset(set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); alarm_thread=pthread_self(); /* For thr_alarm */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 54aa4d421f6..54480b3908d 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -59,9 +59,7 @@ static void *alarm_handler(void *arg); #define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) #endif -#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) static sig_handler thread_alarm(int sig __attribute__((unused))); -#endif static int compare_ulong(void *not_used __attribute__((unused)), byte *a_ptr,byte* b_ptr) @@ -77,21 +75,16 @@ void init_thr_alarm(uint max_alarms) alarm_aborted=0; init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, compare_ulong,NullS); - sigfillset(&full_signal_set); /* Neaded to block signals */ + sigfillset(&full_signal_set); /* Needed to block signals */ pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_alarm,NULL); -#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) -#if defined(HAVE_mit_thread) - sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */ -#else +#ifndef USE_ALARM_THREAD + if (thd_lib_detected != THD_LIB_LT) +#endif { - struct sigaction sact; - sact.sa_flags = 0; - sact.sa_handler = thread_alarm; - sigaction(THR_CLIENT_ALARM, &sact, (struct sigaction*) 0); + my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, + thread_alarm); } -#endif -#endif sigemptyset(&s); sigaddset(&s, THR_SERVER_ALARM); alarm_thread=pthread_self(); @@ -109,13 +102,15 @@ void init_thr_alarm(uint max_alarms) } #elif defined(USE_ONE_SIGNAL_HAND) pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ -#if THR_SERVER_ALARM == THR_CLIENT_ALARM - sigset(THR_CLIENT_ALARM,process_alarm); /* Linuxthreads */ - pthread_sigmask(SIG_UNBLOCK, &s, NULL); -#endif + if (thd_lib_detected == THD_LIB_LT) + { + my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, + process_alarm); /* Linuxthreads */ + pthread_sigmask(SIG_UNBLOCK, &s, NULL); + } #else + my_sigset(THR_SERVER_ALARM, process_alarm); pthread_sigmask(SIG_UNBLOCK, &s, NULL); - sigset(THR_SERVER_ALARM,process_alarm); #endif DBUG_VOID_RETURN; } @@ -163,7 +158,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) now=(ulong) time((time_t*) 0); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); - pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ + pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ if (alarm_aborted > 0) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); @@ -249,7 +244,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) if (alarm_data->malloced) my_free((gptr) alarm_data,MYF(0)); found++; -#ifndef DBUG_OFF +#ifdef DBUG_OFF break; #endif } @@ -258,10 +253,11 @@ void thr_end_alarm(thr_alarm_t *alarmed) if (!found) { if (*alarmed) - fprintf(stderr,"Warning: Didn't find alarm %lx in queue of %d alarms\n", - (long) *alarmed, alarm_queue.elements); - DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n", - (long) *alarmed)); + fprintf(stderr, + "Warning: Didn't find alarm 0x%lx in queue of %d alarms\n", + (long) *alarmed, alarm_queue.elements); + DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n", + (long) *alarmed)); } pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); @@ -283,18 +279,18 @@ sig_handler process_alarm(int sig __attribute__((unused))) This must be first as we can't call DBUG inside an alarm for a normal thread */ -#if THR_SERVER_ALARM == THR_CLIENT_ALARM - if (!pthread_equal(pthread_self(),alarm_thread)) + if (thd_lib_detected == THD_LIB_LT && + !pthread_equal(pthread_self(),alarm_thread)) { #if defined(MAIN) && !defined(__bsdi__) - printf("thread_alarm\n"); fflush(stdout); + printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL - sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ + my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, + process_alarm); /* int. thread system calls */ #endif return; } -#endif /* We have to do do the handling of the alarm in a sub function, @@ -310,7 +306,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) process_alarm_part2(sig); #ifndef USE_ALARM_THREAD #if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) - sigset(THR_SERVER_ALARM,process_alarm); + my_sigset(THR_SERVER_ALARM, process_alarm); #endif pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); @@ -338,7 +334,8 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data->alarmed=1; /* Info to thread */ if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) + pthread_kill(alarm_data->thread, + thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -362,7 +359,8 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data->alarmed=1; /* Info to thread */ DBUG_PRINT("info",("sending signal to waiting thread")); if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, THR_CLIENT_ALARM)) + pthread_kill(alarm_data->thread, + thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -439,16 +437,13 @@ void end_thr_alarm(my_bool free_structures) if (error == ETIME || error == ETIMEDOUT) break; /* Don't wait forever */ } - if (!alarm_queue.elements) + delete_queue(&alarm_queue); + alarm_aborted= 1; + pthread_mutex_unlock(&LOCK_alarm); + if (!alarm_thread_running) /* Safety */ { - delete_queue(&alarm_queue); - alarm_aborted= 1; - pthread_mutex_unlock(&LOCK_alarm); - if (!alarm_thread_running) /* Safety */ - { - pthread_mutex_destroy(&LOCK_alarm); - pthread_cond_destroy(&COND_alarm); - } + pthread_mutex_destroy(&LOCK_alarm); + pthread_cond_destroy(&COND_alarm); } } else @@ -505,17 +500,15 @@ void thr_alarm_info(ALARM_INFO *info) ARGSUSED */ -#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) static sig_handler thread_alarm(int sig) { #ifdef MAIN printf("thread_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL - sigset(sig,thread_alarm); /* int. thread system calls */ + my_sigset(sig, thread_alarm); /* int. thread system calls */ #endif } -#endif #ifdef HAVE_TIMESPEC_TS_SEC @@ -916,7 +909,7 @@ static sig_handler print_signal_warning(int sig) printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); fflush(stdout); #ifdef DONT_REMEMBER_SIGNAL - sigset(sig,print_signal_warning); /* int. thread system calls */ + my_sigset(sig, print_signal_warning); /* int. thread system calls */ #endif #ifndef OS2 if (sig == SIGALRM) @@ -943,9 +936,7 @@ static void *signal_hand(void *arg __attribute__((unused))) sigaddset(&set,SIGINT); sigaddset(&set,SIGQUIT); sigaddset(&set,SIGTERM); -#if THR_CLIENT_ALARM != SIGHUP sigaddset(&set,SIGHUP); -#endif #ifdef SIGTSTP sigaddset(&set,SIGTSTP); #endif @@ -957,7 +948,7 @@ static void *signal_hand(void *arg __attribute__((unused))) #endif #endif /* OS2 */ printf("server alarm: %d thread alarm: %d\n", - THR_SERVER_ALARM,THR_CLIENT_ALARM); + THR_SERVER_ALARM, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); DBUG_PRINT("info",("Starting signal and alarm handling thread")); for(;;) { @@ -1029,11 +1020,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set,SIGTSTP); #endif sigaddset(&set,THR_SERVER_ALARM); - sigdelset(&set,THR_CLIENT_ALARM); + sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); (void) pthread_sigmask(SIG_SETMASK,&set,NULL); #ifdef NOT_USED sigemptyset(&set); - sigaddset(&set,THR_CLIENT_ALARM); + sigaddset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); #endif #endif /* OS2 */ @@ -1083,8 +1074,8 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) } } pthread_mutex_unlock(&LOCK_thread_count); - end_thr_alarm(1); thr_alarm_info(&alarm_info); + end_thr_alarm(1); printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", alarm_info.active_alarms, alarm_info.max_used_alarms, alarm_info.next_alarm_time); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 00bcdbf7132..d70fe9a1c32 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -177,12 +177,6 @@ inline void reset_floating_point_exceptions() } /* cplusplus */ -#if defined(HAVE_LINUXTHREADS) -#define THR_KILL_SIGNAL SIGINT -#else -#define THR_KILL_SIGNAL SIGUSR2 // Can't use this with LinuxThreads -#endif - #ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R #include #else @@ -505,6 +499,7 @@ static void clean_up(bool print_message); static void clean_up_mutexes(void); static int test_if_case_insensitive(const char *dir_name); static void create_pid_file(); +static uint get_thread_lib(void); /**************************************************************************** ** Code to end mysqld @@ -544,7 +539,8 @@ static void close_connections(void) DBUG_PRINT("info",("Waiting for select_thread")); #ifndef DONT_USE_THR_ALARM - if (pthread_kill(select_thread,THR_CLIENT_ALARM)) + if (pthread_kill(select_thread, + thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) break; // allready dead #endif set_timespec(abstime, 2); @@ -844,7 +840,7 @@ extern "C" sig_handler print_signal_warning(int sig) sig,my_thread_id()); } #ifdef DONT_REMEMBER_SIGNAL - sigset(sig,print_signal_warning); /* int. thread system calls */ + my_sigset(sig, print_signal_warning); /* int. thread system calls */ #endif #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) if (sig == SIGALRM) @@ -1841,8 +1837,11 @@ static void init_signals(void) DBUG_ENTER("init_signals"); if (test_flags & TEST_SIGINT) - sigset(THR_KILL_SIGNAL,end_thread_signal); - sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! + { + my_sigset(thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2, + end_thread_signal); + } + my_sigset(THR_SERVER_ALARM, print_signal_warning); // Should never be called! if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) { @@ -1877,7 +1876,7 @@ static void init_signals(void) #endif (void) sigemptyset(&set); #ifdef THREAD_SPECIFIC_SIGPIPE - sigset(SIGPIPE,abort_thread); + my_sigset(SIGPIPE, abort_thread); sigaddset(&set,SIGPIPE); #else (void) signal(SIGPIPE,SIG_IGN); // Can't know which thread @@ -1903,8 +1902,12 @@ static void init_signals(void) #endif sigaddset(&set,THR_SERVER_ALARM); if (test_flags & TEST_SIGINT) - sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT - sigdelset(&set,THR_CLIENT_ALARM); // For alarms + { + // May be SIGINT + sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2); + } + // For alarms + sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); sigprocmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; @@ -1959,23 +1962,19 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) */ init_thr_alarm(max_connections + global_system_variables.max_insert_delayed_threads + 10); -#if SIGINT != THR_KILL_SIGNAL - if (test_flags & TEST_SIGINT) + if (thd_lib_detected != THD_LIB_LT && test_flags & TEST_SIGINT) { (void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigaddset(&set,SIGINT); // For debugging (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL); } -#endif (void) sigemptyset(&set); // Setup up SIGINT for debug #ifdef USE_ONE_SIGNAL_HAND (void) sigaddset(&set,THR_SERVER_ALARM); // For alarms #endif #ifndef IGNORE_SIGHUP_SIGQUIT (void) sigaddset(&set,SIGQUIT); -#if THR_CLIENT_ALARM != SIGHUP (void) sigaddset(&set,SIGHUP); -#endif #endif (void) sigaddset(&set,SIGTERM); (void) sigaddset(&set,SIGTSTP); @@ -2236,8 +2235,8 @@ int main(int argc, char **argv) MY_INIT(argv[0]); // init my_sys library & pthreads tzset(); // Set tzname + thd_lib_detected= get_thread_lib(); start_time=time((time_t*) 0); - #ifdef OS2 { // fix timezone for daylight saving @@ -5549,6 +5548,22 @@ static void create_pid_file() } +static uint get_thread_lib(void) +{ + char buff[64]; + +#ifdef _CS_GNU_LIBPTHREAD_VERSION + confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); + + if (!strncasecmp(buff, "NPTL", 4)) + return THD_LIB_NPTL; + else if (!strncasecmp(buff, "linuxthreads", 12)) + return THD_LIB_LT; +#endif + return THD_LIB_OTHER; +} + + /***************************************************************************** Instantiate templates *****************************************************************************/ From 457d4315568c7d26340bea4be8a2c8d96960916c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 24 Jan 2007 09:41:40 +0700 Subject: [PATCH 2/9] Bug#25668 mysqld may core if cluster disconnected - recommit in 4.1 --- sql/ha_ndbcluster.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index fd9a5720e3d..d16e00f4e52 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5373,7 +5373,7 @@ ndb_get_table_statistics(ha_ndbcluster* file, bool report_error, Ndb* ndb, retry: if(report_error) { - if (file) + if (file && pTrans) { reterr= file->ndb_err(pTrans); } From 2ec2fa6d08b9720307e8bc85aaa797fd05b565a2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jan 2007 20:10:31 +0200 Subject: [PATCH 3/9] Cleanup of thread-type (linuxthread or NTPL) detection code Move get_thread_lib to mysys/my_pthread.c Set 'thr_client_alarm' to signal number used by thr_alarm to give alarms include/my_global.h: Fixed to be same as in 5.1 include/my_pthread.h: Move things around to be more in line with rest of code include/thr_alarm.h: extern of thr_client_alarm mysys/default.c: Fixed two wrong pointer incrementations. mysys/my_pthread.c: Cleanup: Use variable thr_client_alarm mysys/my_thr_init.c: Detect thread library at startup mysys/thr_alarm.c: Set thr_client_alarm depending on which thread library we are using sql/mysqld.cc: Move get_thread_lib to mysys/my_pthread.c --- include/my_global.h | 5 +---- include/my_pthread.h | 16 ++++++++-------- include/thr_alarm.h | 2 ++ mysys/default.c | 4 ++-- mysys/my_pthread.c | 4 +++- mysys/my_thr_init.c | 20 ++++++++++++++++++++ mysys/thr_alarm.c | 26 +++++++++++++------------- sql/mysqld.cc | 34 +++++++++------------------------- 8 files changed, 58 insertions(+), 53 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index e6bf9a9b840..f0e600e386d 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -348,10 +348,7 @@ int __void__; #endif /* Define some useful general macros */ -#if defined(__cplusplus) && defined(__GNUC__) -#define max(a, b) ((a) >? (b)) -#define min(a, b) ((a) (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index e1a7ecab4ab..9d5e78bba44 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -28,14 +28,6 @@ extern "C" { #endif /* __cplusplus */ -/* Thread library */ - -#define THD_LIB_OTHER 1 -#define THD_LIB_NPTL 2 -#define THD_LIB_LT 4 - -extern uint thd_lib_detected; - #if defined(__WIN__) || defined(OS2) #ifdef OS2 @@ -684,6 +676,14 @@ extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); */ extern pthread_t shutdown_th, main_th, signal_th; +/* Which kind of thread library is in use */ + +#define THD_LIB_OTHER 1 +#define THD_LIB_NPTL 2 +#define THD_LIB_LT 4 + +extern uint thd_lib_detected; + /* statistics_xxx functions are for not essential statistic */ #ifndef thread_safe_increment diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 0c26a67acf4..ef6aaf49f77 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -93,6 +93,8 @@ typedef struct st_alarm { my_bool malloced; } ALARM; +extern uint thr_client_alarm; + #define thr_alarm_init(A) (*(A))=0 #define thr_alarm_in_use(A) (*(A)!= 0) void init_thr_alarm(uint max_alarm); diff --git a/mysys/default.c b/mysys/default.c index 25e283a9650..911f516dad8 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -282,7 +282,7 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, { char **ext; - for (ext= (char**) f_extensions; *ext; *ext++) + for (ext= (char**) f_extensions; *ext; ext++) { int error; if ((error= search_default_file_with_ext(args, alloc, dir, *ext, @@ -543,7 +543,7 @@ void print_defaults(const char *conf_file, const char **groups) #endif for (dirs=default_directories ; *dirs; dirs++) { - for (ext= (char**) f_extensions; *ext; *ext++) + for (ext= (char**) f_extensions; *ext; ext++) { const char *pos; char *end; diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 3eaf27844b2..19766a2d195 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -322,7 +322,9 @@ void *sigwait_thread(void *set_arg) sigaction(i, &sact, (struct sigaction*) 0); } } - sigaddset(set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + /* Ensure that init_thr_alarm() is called */ + DBUG_ASSERT(thr_client_alarm); + sigaddset(set, thr_client_alarm); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); alarm_thread=pthread_self(); /* For thr_alarm */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 878a861bc94..51b31f78a1c 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -44,6 +44,8 @@ pthread_mutexattr_t my_fast_mutexattr; pthread_mutexattr_t my_errchk_mutexattr; #endif +static uint get_thread_lib(void); + /* initialize thread environment @@ -57,6 +59,8 @@ pthread_mutexattr_t my_errchk_mutexattr; my_bool my_thread_global_init(void) { + thd_lib_detected= get_thread_lib(); + if (pthread_key_create(&THR_KEY_mysys,0)) { fprintf(stderr,"Can't initialize threads: error %d\n",errno); @@ -276,4 +280,20 @@ const char *my_thread_name(void) } #endif /* DBUG_OFF */ + +static uint get_thread_lib(void) +{ + char buff[64]; + +#ifdef _CS_GNU_LIBPTHREAD_VERSION + confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); + + if (!strncasecmp(buff, "NPTL", 4)) + return THD_LIB_NPTL; + if (!strncasecmp(buff, "linuxthreads", 12)) + return THD_LIB_LT; +#endif + return THD_LIB_OTHER; +} + #endif /* THREAD */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 54480b3908d..8f342e269de 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -37,6 +37,7 @@ #define ETIME ETIMEDOUT #endif +uint thr_client_alarm; static int alarm_aborted=1; /* No alarm thread */ my_bool thr_alarm_inited= 0; volatile my_bool alarm_thread_running= 0; @@ -78,12 +79,15 @@ void init_thr_alarm(uint max_alarms) sigfillset(&full_signal_set); /* Needed to block signals */ pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_alarm,NULL); + if (thd_lib_detected == THD_LIB_LT) + thr_client_alarm= SIGALRM; + else + thr_client_alarm= SIGUSR1; #ifndef USE_ALARM_THREAD if (thd_lib_detected != THD_LIB_LT) #endif { - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, - thread_alarm); + my_sigset(thr_client_alarm, thread_alarm); } sigemptyset(&s); sigaddset(&s, THR_SERVER_ALARM); @@ -104,8 +108,7 @@ void init_thr_alarm(uint max_alarms) pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ if (thd_lib_detected == THD_LIB_LT) { - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, - process_alarm); /* Linuxthreads */ + my_sigset(thr_client_alarm, process_alarm); /* Linuxthreads */ pthread_sigmask(SIG_UNBLOCK, &s, NULL); } #else @@ -286,8 +289,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, - process_alarm); /* int. thread system calls */ + my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ #endif return; } @@ -334,8 +336,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data->alarmed=1; /* Info to thread */ if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, - thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) + pthread_kill(alarm_data->thread, thr_client_alarm)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -359,8 +360,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data->alarmed=1; /* Info to thread */ DBUG_PRINT("info",("sending signal to waiting thread")); if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, - thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) + pthread_kill(alarm_data->thread, thr_client_alarm)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -948,7 +948,7 @@ static void *signal_hand(void *arg __attribute__((unused))) #endif #endif /* OS2 */ printf("server alarm: %d thread alarm: %d\n", - THR_SERVER_ALARM, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + THR_SERVER_ALARM, thr_client_alarm); DBUG_PRINT("info",("Starting signal and alarm handling thread")); for(;;) { @@ -1020,11 +1020,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set,SIGTSTP); #endif sigaddset(&set,THR_SERVER_ALARM); - sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + sigdelset(&set, thr_client_alarm); (void) pthread_sigmask(SIG_SETMASK,&set,NULL); #ifdef NOT_USED sigemptyset(&set); - sigaddset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + sigaddset(&set, thr_client_alarm); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); #endif #endif /* OS2 */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d70fe9a1c32..43d76f28007 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -459,6 +459,7 @@ pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped, pthread_cond_t COND_thread_cache,COND_flush_thread_cache; pthread_t signal_thread; pthread_attr_t connection_attrib; +static uint thr_kill_signal; #ifdef __WIN__ #undef getpid @@ -499,7 +500,6 @@ static void clean_up(bool print_message); static void clean_up_mutexes(void); static int test_if_case_insensitive(const char *dir_name); static void create_pid_file(); -static uint get_thread_lib(void); /**************************************************************************** ** Code to end mysqld @@ -539,8 +539,7 @@ static void close_connections(void) DBUG_PRINT("info",("Waiting for select_thread")); #ifndef DONT_USE_THR_ALARM - if (pthread_kill(select_thread, - thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) + if (pthread_kill(select_thread, thr_client_alarm)) break; // allready dead #endif set_timespec(abstime, 2); @@ -1838,8 +1837,7 @@ static void init_signals(void) if (test_flags & TEST_SIGINT) { - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2, - end_thread_signal); + my_sigset(thr_kill_signal, end_thread_signal); } my_sigset(THR_SERVER_ALARM, print_signal_warning); // Should never be called! @@ -1904,10 +1902,10 @@ static void init_signals(void) if (test_flags & TEST_SIGINT) { // May be SIGINT - sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2); + sigdelset(&set, thr_kill_signal); } // For alarms - sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + sigdelset(&set, thr_client_alarm); sigprocmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; @@ -1962,7 +1960,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) */ init_thr_alarm(max_connections + global_system_variables.max_insert_delayed_threads + 10); - if (thd_lib_detected != THD_LIB_LT && test_flags & TEST_SIGINT) + if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT)) { (void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigaddset(&set,SIGINT); // For debugging @@ -2235,7 +2233,6 @@ int main(int argc, char **argv) MY_INIT(argv[0]); // init my_sys library & pthreads tzset(); // Set tzname - thd_lib_detected= get_thread_lib(); start_time=time((time_t*) 0); #ifdef OS2 { @@ -2253,6 +2250,9 @@ int main(int argc, char **argv) } #endif + /* Set signal used to kill MySQL */ + thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2; + /* Init mutexes for the global MYSQL_LOG objects. As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of @@ -5548,22 +5548,6 @@ static void create_pid_file() } -static uint get_thread_lib(void) -{ - char buff[64]; - -#ifdef _CS_GNU_LIBPTHREAD_VERSION - confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); - - if (!strncasecmp(buff, "NPTL", 4)) - return THD_LIB_NPTL; - else if (!strncasecmp(buff, "linuxthreads", 12)) - return THD_LIB_LT; -#endif - return THD_LIB_OTHER; -} - - /***************************************************************************** Instantiate templates *****************************************************************************/ From cdf6001aeb24d7085ab5f053b31858d95c382e06 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 Jan 2007 18:52:26 +0200 Subject: [PATCH 4/9] Cleanup of thread-type (linuxthread or NTPL) detection code Move get_thread_lib to mysys/my_pthread.c Set 'thr_client_alarm' to signal number used by thr_alarm to give alarms include/my_global.h: Fixed to be same as in 5.1 include/my_pthread.h: Move things around to be more in line with rest of code mysys/default.c: Fixed two wrong pointer incrementations. mysys/my_pthread.c: Cleanup: Use variable thr_client_alarm mysys/my_thr_init.c: Detect thread library at startup. Set also thr_client_alarm signal here, so that we get it in init_signals() in mysqld mysys/thr_alarm.c: Set thr_client_alarm depending on which thread library we are using sql/mysqld.cc: Move get_thread_lib to mysys/my_pthread.c --- include/my_global.h | 5 +---- include/my_pthread.h | 17 +++++++++-------- mysys/default.c | 4 ++-- mysys/my_pthread.c | 5 ++++- mysys/my_thr_init.c | 25 +++++++++++++++++++++++++ mysys/thr_alarm.c | 21 ++++++++------------- sql/mysqld.cc | 34 +++++++++------------------------- 7 files changed, 58 insertions(+), 53 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index e6bf9a9b840..f0e600e386d 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -348,10 +348,7 @@ int __void__; #endif /* Define some useful general macros */ -#if defined(__cplusplus) && defined(__GNUC__) -#define max(a, b) ((a) >? (b)) -#define min(a, b) ((a) (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index e1a7ecab4ab..a336d4dc288 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -28,14 +28,6 @@ extern "C" { #endif /* __cplusplus */ -/* Thread library */ - -#define THD_LIB_OTHER 1 -#define THD_LIB_NPTL 2 -#define THD_LIB_LT 4 - -extern uint thd_lib_detected; - #if defined(__WIN__) || defined(OS2) #ifdef OS2 @@ -684,6 +676,15 @@ extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); */ extern pthread_t shutdown_th, main_th, signal_th; +/* Which kind of thread library is in use */ + +#define THD_LIB_OTHER 1 +#define THD_LIB_NPTL 2 +#define THD_LIB_LT 4 + +extern uint thd_lib_detected; +extern uint thr_client_alarm; + /* statistics_xxx functions are for not essential statistic */ #ifndef thread_safe_increment diff --git a/mysys/default.c b/mysys/default.c index 25e283a9650..911f516dad8 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -282,7 +282,7 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc, { char **ext; - for (ext= (char**) f_extensions; *ext; *ext++) + for (ext= (char**) f_extensions; *ext; ext++) { int error; if ((error= search_default_file_with_ext(args, alloc, dir, *ext, @@ -543,7 +543,7 @@ void print_defaults(const char *conf_file, const char **groups) #endif for (dirs=default_directories ; *dirs; dirs++) { - for (ext= (char**) f_extensions; *ext; *ext++) + for (ext= (char**) f_extensions; *ext; ext++) { const char *pos; char *end; diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 3eaf27844b2..fd716448e43 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -32,6 +32,7 @@ #endif uint thd_lib_detected; +uint thr_client_alarm; #ifndef my_pthread_setprio void my_pthread_setprio(pthread_t thread_id,int prior) @@ -322,7 +323,9 @@ void *sigwait_thread(void *set_arg) sigaction(i, &sact, (struct sigaction*) 0); } } - sigaddset(set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + /* Ensure that init_thr_alarm() is called */ + DBUG_ASSERT(thr_client_alarm); + sigaddset(set, thr_client_alarm); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); alarm_thread=pthread_self(); /* For thr_alarm */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 878a861bc94..5729f27b7a7 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -21,6 +21,7 @@ #include "mysys_priv.h" #include +#include #ifdef THREAD #ifdef USE_TLS @@ -44,6 +45,8 @@ pthread_mutexattr_t my_fast_mutexattr; pthread_mutexattr_t my_errchk_mutexattr; #endif +static uint get_thread_lib(void); + /* initialize thread environment @@ -57,6 +60,12 @@ pthread_mutexattr_t my_errchk_mutexattr; my_bool my_thread_global_init(void) { + thd_lib_detected= get_thread_lib(); + if (thd_lib_detected == THD_LIB_LT) + thr_client_alarm= SIGALRM; + else + thr_client_alarm= SIGUSR1; + if (pthread_key_create(&THR_KEY_mysys,0)) { fprintf(stderr,"Can't initialize threads: error %d\n",errno); @@ -276,4 +285,20 @@ const char *my_thread_name(void) } #endif /* DBUG_OFF */ + +static uint get_thread_lib(void) +{ + char buff[64]; + +#ifdef _CS_GNU_LIBPTHREAD_VERSION + confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); + + if (!strncasecmp(buff, "NPTL", 4)) + return THD_LIB_NPTL; + if (!strncasecmp(buff, "linuxthreads", 12)) + return THD_LIB_LT; +#endif + return THD_LIB_OTHER; +} + #endif /* THREAD */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 54480b3908d..fd1e48d730a 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -82,8 +82,7 @@ void init_thr_alarm(uint max_alarms) if (thd_lib_detected != THD_LIB_LT) #endif { - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, - thread_alarm); + my_sigset(thr_client_alarm, thread_alarm); } sigemptyset(&s); sigaddset(&s, THR_SERVER_ALARM); @@ -104,8 +103,7 @@ void init_thr_alarm(uint max_alarms) pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ if (thd_lib_detected == THD_LIB_LT) { - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, - process_alarm); /* Linuxthreads */ + my_sigset(thr_client_alarm, process_alarm); /* Linuxthreads */ pthread_sigmask(SIG_UNBLOCK, &s, NULL); } #else @@ -286,8 +284,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1, - process_alarm); /* int. thread system calls */ + my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ #endif return; } @@ -334,8 +331,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data=(ALARM*) queue_element(&alarm_queue,i); alarm_data->alarmed=1; /* Info to thread */ if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, - thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) + pthread_kill(alarm_data->thread, thr_client_alarm)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -359,8 +355,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm_data->alarmed=1; /* Info to thread */ DBUG_PRINT("info",("sending signal to waiting thread")); if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, - thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) + pthread_kill(alarm_data->thread, thr_client_alarm)) { #ifdef MAIN printf("Warning: pthread_kill couldn't find thread!!!\n"); @@ -948,7 +943,7 @@ static void *signal_hand(void *arg __attribute__((unused))) #endif #endif /* OS2 */ printf("server alarm: %d thread alarm: %d\n", - THR_SERVER_ALARM, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + THR_SERVER_ALARM, thr_client_alarm); DBUG_PRINT("info",("Starting signal and alarm handling thread")); for(;;) { @@ -1020,11 +1015,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set,SIGTSTP); #endif sigaddset(&set,THR_SERVER_ALARM); - sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + sigdelset(&set, thr_client_alarm); (void) pthread_sigmask(SIG_SETMASK,&set,NULL); #ifdef NOT_USED sigemptyset(&set); - sigaddset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + sigaddset(&set, thr_client_alarm); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); #endif #endif /* OS2 */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d70fe9a1c32..43d76f28007 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -459,6 +459,7 @@ pthread_cond_t COND_refresh,COND_thread_count, COND_slave_stopped, pthread_cond_t COND_thread_cache,COND_flush_thread_cache; pthread_t signal_thread; pthread_attr_t connection_attrib; +static uint thr_kill_signal; #ifdef __WIN__ #undef getpid @@ -499,7 +500,6 @@ static void clean_up(bool print_message); static void clean_up_mutexes(void); static int test_if_case_insensitive(const char *dir_name); static void create_pid_file(); -static uint get_thread_lib(void); /**************************************************************************** ** Code to end mysqld @@ -539,8 +539,7 @@ static void close_connections(void) DBUG_PRINT("info",("Waiting for select_thread")); #ifndef DONT_USE_THR_ALARM - if (pthread_kill(select_thread, - thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1)) + if (pthread_kill(select_thread, thr_client_alarm)) break; // allready dead #endif set_timespec(abstime, 2); @@ -1838,8 +1837,7 @@ static void init_signals(void) if (test_flags & TEST_SIGINT) { - my_sigset(thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2, - end_thread_signal); + my_sigset(thr_kill_signal, end_thread_signal); } my_sigset(THR_SERVER_ALARM, print_signal_warning); // Should never be called! @@ -1904,10 +1902,10 @@ static void init_signals(void) if (test_flags & TEST_SIGINT) { // May be SIGINT - sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2); + sigdelset(&set, thr_kill_signal); } // For alarms - sigdelset(&set, thd_lib_detected == THD_LIB_LT ? SIGALRM : SIGUSR1); + sigdelset(&set, thr_client_alarm); sigprocmask(SIG_SETMASK,&set,NULL); pthread_sigmask(SIG_SETMASK,&set,NULL); DBUG_VOID_RETURN; @@ -1962,7 +1960,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) */ init_thr_alarm(max_connections + global_system_variables.max_insert_delayed_threads + 10); - if (thd_lib_detected != THD_LIB_LT && test_flags & TEST_SIGINT) + if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT)) { (void) sigemptyset(&set); // Setup up SIGINT for debug (void) sigaddset(&set,SIGINT); // For debugging @@ -2235,7 +2233,6 @@ int main(int argc, char **argv) MY_INIT(argv[0]); // init my_sys library & pthreads tzset(); // Set tzname - thd_lib_detected= get_thread_lib(); start_time=time((time_t*) 0); #ifdef OS2 { @@ -2253,6 +2250,9 @@ int main(int argc, char **argv) } #endif + /* Set signal used to kill MySQL */ + thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2; + /* Init mutexes for the global MYSQL_LOG objects. As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of @@ -5548,22 +5548,6 @@ static void create_pid_file() } -static uint get_thread_lib(void) -{ - char buff[64]; - -#ifdef _CS_GNU_LIBPTHREAD_VERSION - confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); - - if (!strncasecmp(buff, "NPTL", 4)) - return THD_LIB_NPTL; - else if (!strncasecmp(buff, "linuxthreads", 12)) - return THD_LIB_LT; -#endif - return THD_LIB_OTHER; -} - - /***************************************************************************** Instantiate templates *****************************************************************************/ From f7b3c7c531cb4cc3960e64c96a670949ee3a2ffa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 Jan 2007 16:15:20 +0400 Subject: [PATCH 5/9] WL#3567 - MERGE engine: a check for underlying table conformance When a merge table is opened compare column and key definition of underlying tables against column and key definition of merge table. If any of underlying tables have different column/key definition refuse to open merge table. mysql-test/r/merge.result: A test case for WL#3456. mysql-test/t/merge.test: A test case for WL#3456. sql/ha_myisam.cc: Moved a part of code that converts TABLE object to MyISAM key and column definition to a separate function. Added check_definition() function that compares MyISAM table definitions. sql/ha_myisammrg.cc: Check if underlying table definition conforms to merge table definition, and in case underlying table definition differs, refuse to open merge table. --- mysql-test/r/merge.result | 22 +- mysql-test/t/merge.test | 29 ++- sql/ha_myisam.cc | 491 ++++++++++++++++++++++++-------------- sql/ha_myisammrg.cc | 42 +++- 4 files changed, 404 insertions(+), 180 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index a1ef7597143..eb333cdadb7 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -770,7 +770,7 @@ CREATE TABLE t1(a INT); INSERT INTO t1 VALUES(2),(1); CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); SELECT * FROM t2 WHERE a=2; -ERROR HY000: Got error 124 from storage engine +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist DROP TABLE t1, t2; CREATE TABLE t1(a INT) ENGINE=MEMORY; CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); @@ -781,3 +781,23 @@ CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); SELECT * FROM t2; ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist DROP TABLE t2; +CREATE TABLE t1(a INT, b TEXT); +CREATE TABLE tm1(a TEXT, b INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM tm1; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, tm1; +CREATE TABLE t1(a SMALLINT, b SMALLINT); +CREATE TABLE tm1(a INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM tm1; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, tm1; +CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(a, b)); +CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1); +SELECT * FROM tm1; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, tm1; +CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(b)); +CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1); +SELECT * FROM tm1; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, tm1; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index bb03b7b8d62..700a807e62c 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -383,7 +383,7 @@ drop table t1, t2, t3; CREATE TABLE t1(a INT); INSERT INTO t1 VALUES(2),(1); CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); ---error 1030 +--error 1168 SELECT * FROM t2 WHERE a=2; DROP TABLE t1, t2; @@ -401,4 +401,31 @@ CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); SELECT * FROM t2; DROP TABLE t2; +# +# Underlying table definition conformance tests. +# +CREATE TABLE t1(a INT, b TEXT); +CREATE TABLE tm1(a TEXT, b INT) ENGINE=MERGE UNION=(t1); +--error 1168 +SELECT * FROM tm1; +DROP TABLE t1, tm1; + +CREATE TABLE t1(a SMALLINT, b SMALLINT); +CREATE TABLE tm1(a INT) ENGINE=MERGE UNION=(t1); +--error 1168 +SELECT * FROM tm1; +DROP TABLE t1, tm1; + +CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(a, b)); +CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1); +--error 1168 +SELECT * FROM tm1; +DROP TABLE t1, tm1; + +CREATE TABLE t1(a SMALLINT, b SMALLINT, KEY(b)); +CREATE TABLE tm1(a SMALLINT, b SMALLINT, KEY(a)) ENGINE=MERGE UNION=(t1); +--error 1168 +SELECT * FROM tm1; +DROP TABLE t1, tm1; + # End of 4.1 tests diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2e29d929352..2cec03a51db 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -91,6 +91,296 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, return; } + +/* + Convert TABLE object to MyISAM key and column definition + + SYNOPSIS + table2myisam() + table_arg in TABLE object. + keydef_out out MyISAM key definition. + recinfo_out out MyISAM column definition. + records_out out Number of fields. + + DESCRIPTION + This function will allocate and initialize MyISAM key and column + definition for further use in mi_create or for a check for underlying + table conformance in merge engine. + + RETURN VALUE + 0 OK + !0 error code +*/ + +int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, + MI_COLUMNDEF **recinfo_out, uint *records_out) +{ + uint i, j, recpos, minpos, fieldpos, temp_length, length; + uint options= table_arg->db_options_in_use; + enum ha_base_keytype type= HA_KEYTYPE_BINARY; + KEY *pos; + MI_KEYDEF *keydef; + MI_COLUMNDEF *recinfo, *recinfo_pos; + HA_KEYSEG *keyseg; + + DBUG_ENTER("table2myisam"); + if (!(my_multi_malloc(MYF(MY_WME), + recinfo_out, (table_arg->fields * 2 + 2) * sizeof(MI_COLUMNDEF), + keydef_out, table_arg->keys * sizeof(MI_KEYDEF), + &keyseg, + (table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG), + NullS))) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */ + keydef= *keydef_out; + recinfo= *recinfo_out; + pos= table_arg->key_info; + for (i= 0; i < table_arg->keys; i++, pos++) + { + keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); + keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ? + (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) : + pos->algorithm; + keydef[i].seg= keyseg; + keydef[i].keysegs= pos->key_parts; + for (j= 0; j < pos->key_parts; j++) + { + keydef[i].seg[j].flag= pos->key_part[j].key_part_flag; + Field *field= pos->key_part[j].field; + type= field->key_type(); + + if (options & HA_OPTION_PACK_KEYS || + (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY | + HA_SPACE_PACK_USED))) + { + if (pos->key_part[j].length > 8 && + (type == HA_KEYTYPE_TEXT || + type == HA_KEYTYPE_NUM || + (type == HA_KEYTYPE_BINARY && !field->zero_pack()))) + { + /* No blobs here */ + if (j == 0) + keydef[i].flag|= HA_PACK_KEY; + if (!(field->flags & ZEROFILL_FLAG) && + (field->type() == FIELD_TYPE_STRING || + field->type() == FIELD_TYPE_VAR_STRING || + ((int) (pos->key_part[j].length - field->decimals())) >= 4)) + keydef[i].seg[j].flag|= HA_SPACE_PACK; + } + else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16)) + keydef[i].flag|= HA_BINARY_PACK_KEY; + } + keydef[i].seg[j].type= (int) type; + keydef[i].seg[j].start= pos->key_part[j].offset; + keydef[i].seg[j].length= pos->key_part[j].length; + keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end= 0; + keydef[i].seg[j].language= field->charset()->number; + + if (field->null_ptr) + { + keydef[i].seg[j].null_bit= field->null_bit; + keydef[i].seg[j].null_pos= (uint) (field->null_ptr- + (uchar*) table_arg->record[0]); + } + else + { + keydef[i].seg[j].null_bit= 0; + keydef[i].seg[j].null_pos= 0; + } + if (field->type() == FIELD_TYPE_BLOB || + field->type() == FIELD_TYPE_GEOMETRY) + { + keydef[i].seg[j].flag|= HA_BLOB_PART; + /* save number of bytes used to pack length */ + keydef[i].seg[j].bit_start= (uint) (field->pack_length() - + table_arg->blob_ptr_size); + } + } + keyseg+= pos->key_parts; + } + if (table_arg->found_next_number_field) + keydef[table_arg->next_number_index].flag|= HA_AUTO_KEY; + recpos= 0; + recinfo_pos= recinfo; + while (recpos < (uint) table_arg->reclength) + { + Field **field, *found= 0; + minpos= table_arg->reclength; + length= 0; + + for (field= table_arg->field; *field; field++) + { + if ((fieldpos= (*field)->offset()) >= recpos && + fieldpos <= minpos) + { + /* skip null fields */ + if (!(temp_length= (*field)->pack_length())) + continue; /* Skip null-fields */ + if (! found || fieldpos < minpos || + (fieldpos == minpos && temp_length < length)) + { + minpos= fieldpos; + found= *field; + length= temp_length; + } + } + } + DBUG_PRINT("loop", ("found: %lx recpos: %d minpos: %d length: %d", + (long) found, recpos, minpos, length)); + if (recpos != minpos) + { // Reserved space (Null bits?) + bzero((char*) recinfo_pos, sizeof(*recinfo_pos)); + recinfo_pos->type= (int) FIELD_NORMAL; + recinfo_pos++->length= (uint16) (minpos - recpos); + } + if (!found) + break; + + if (found->flags & BLOB_FLAG) + { + recinfo_pos->type= (int) FIELD_BLOB; + } + else if (!(options & HA_OPTION_PACK_RECORD)) + recinfo_pos->type= (int) FIELD_NORMAL; + else if (found->zero_pack()) + recinfo_pos->type= (int) FIELD_SKIP_ZERO; + else + recinfo_pos->type= (int) ((length <= 3 || + (found->flags & ZEROFILL_FLAG)) ? + FIELD_NORMAL : + found->type() == FIELD_TYPE_STRING || + found->type() == FIELD_TYPE_VAR_STRING ? + FIELD_SKIP_ENDSPACE : + FIELD_SKIP_PRESPACE); + if (found->null_ptr) + { + recinfo_pos->null_bit= found->null_bit; + recinfo_pos->null_pos= (uint) (found->null_ptr - + (uchar*) table_arg->record[0]); + } + else + { + recinfo_pos->null_bit= 0; + recinfo_pos->null_pos= 0; + } + (recinfo_pos++)->length= (uint16) length; + recpos= minpos + length; + DBUG_PRINT("loop", ("length: %d type: %d", + recinfo_pos[-1].length,recinfo_pos[-1].type)); + } + *records_out= (uint) (recinfo_pos - recinfo); + DBUG_RETURN(0); +} + + +/* + Check for underlying table conformance + + SYNOPSIS + check_definition() + t1_keyinfo in First table key definition + t1_recinfo in First table record definition + t1_keys in Number of keys in first table + t1_recs in Number of records in first table + t2_keyinfo in Second table key definition + t2_recinfo in Second table record definition + t2_keys in Number of keys in second table + t2_recs in Number of records in second table + strict in Strict check switch + + DESCRIPTION + This function compares two MyISAM definitions. By intention it was done + to compare merge table definition against underlying table definition. + It may also be used to compare dot-frm and MYI definitions of MyISAM + table as well to compare different MyISAM table definitions. + + For merge table it is not required that number of keys in merge table + must exactly match number of keys in underlying table. When calling this + function for underlying table conformance check, 'strict' flag must be + set to false, and converted merge definition must be passed as t1_*. + + Otherwise 'strict' flag must be set to 1 and it is not required to pass + converted dot-frm definition as t1_*. + + RETURN VALUE + 0 - Equal definitions. + 1 - Different definitions. +*/ + +int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, + uint t1_keys, uint t1_recs, + MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo, + uint t2_keys, uint t2_recs, bool strict) +{ + uint i, j; + DBUG_ENTER("check_definition"); + if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys)) + { + DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u", + t1_keys, t2_keys)); + DBUG_RETURN(1); + } + if (t1_recs != t2_recs) + { + DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u", + t1_recs, t2_recs)); + DBUG_RETURN(1); + } + for (i= 0; i < t1_keys; i++) + { + HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg; + HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg; + if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs || + t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg) + { + DBUG_PRINT("error", ("Key %d has different definition", i)); + DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d", + t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg)); + DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d", + t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg)); + DBUG_RETURN(1); + } + for (j= t1_keyinfo[i].keysegs; j--;) + { + if (t1_keysegs[j].type != t2_keysegs[j].type || + t1_keysegs[j].language != t2_keysegs[j].language || + t1_keysegs[j].null_bit != t2_keysegs[j].null_bit || + t1_keysegs[j].length != t2_keysegs[j].length) + { + DBUG_PRINT("error", ("Key segment %d (key %d) has different " + "definition", j, i)); + DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, " + "t1_length=%d", + t1_keysegs[j].type, t1_keysegs[j].language, + t1_keysegs[j].null_bit, t1_keysegs[j].length)); + DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, " + "t2_length=%d", + t2_keysegs[j].type, t2_keysegs[j].language, + t2_keysegs[j].null_bit, t2_keysegs[j].length)); + + DBUG_RETURN(1); + } + } + } + for (i= 0; i < t1_recs; i++) + { + MI_COLUMNDEF *t1_rec= &t1_recinfo[i]; + MI_COLUMNDEF *t2_rec= &t2_recinfo[i]; + if (t1_rec->type != t2_rec->type || + t1_rec->length != t2_rec->length || + t1_rec->null_bit != t2_rec->null_bit) + { + DBUG_PRINT("error", ("Field %d has different definition", i)); + DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d", + t1_rec->type, t1_rec->length, t1_rec->null_bit)); + DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d", + t2_rec->type, t2_rec->length, t2_rec->null_bit)); + DBUG_RETURN(1); + } + } + DBUG_RETURN(0); +} + + extern "C" { volatile my_bool *killed_ptr(MI_CHECK *param) @@ -1345,181 +1635,30 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, HA_CREATE_INFO *info) { int error; - uint i,j,recpos,minpos,fieldpos,temp_length,length, create_flags= 0; - bool found_real_auto_increment=0; - enum ha_base_keytype type; + uint create_flags= 0, options= table_arg->db_options_in_use, records; char buff[FN_REFLEN]; - KEY *pos; MI_KEYDEF *keydef; - MI_COLUMNDEF *recinfo,*recinfo_pos; - HA_KEYSEG *keyseg; - uint options=table_arg->db_options_in_use; - DBUG_ENTER("ha_myisam::create"); - - type=HA_KEYTYPE_BINARY; // Keep compiler happy - if (!(my_multi_malloc(MYF(MY_WME), - &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF), - &keydef, table_arg->keys*sizeof(MI_KEYDEF), - &keyseg, - ((table_arg->key_parts + table_arg->keys) * - sizeof(HA_KEYSEG)), - NullS))) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - - pos=table_arg->key_info; - for (i=0; i < table_arg->keys ; i++, pos++) - { - keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL)); - keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ? - (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) : - pos->algorithm; - keydef[i].seg=keyseg; - keydef[i].keysegs=pos->key_parts; - for (j=0 ; j < pos->key_parts ; j++) - { - keydef[i].seg[j].flag=pos->key_part[j].key_part_flag; - Field *field=pos->key_part[j].field; - type=field->key_type(); - - if (options & HA_OPTION_PACK_KEYS || - (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY | - HA_SPACE_PACK_USED))) - { - if (pos->key_part[j].length > 8 && - (type == HA_KEYTYPE_TEXT || - type == HA_KEYTYPE_NUM || - (type == HA_KEYTYPE_BINARY && !field->zero_pack()))) - { - /* No blobs here */ - if (j == 0) - keydef[i].flag|=HA_PACK_KEY; - if (!(field->flags & ZEROFILL_FLAG) && - (field->type() == FIELD_TYPE_STRING || - field->type() == FIELD_TYPE_VAR_STRING || - ((int) (pos->key_part[j].length - field->decimals())) - >= 4)) - keydef[i].seg[j].flag|=HA_SPACE_PACK; - } - else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16)) - keydef[i].flag|= HA_BINARY_PACK_KEY; - } - keydef[i].seg[j].type= (int) type; - keydef[i].seg[j].start= pos->key_part[j].offset; - keydef[i].seg[j].length= pos->key_part[j].length; - keydef[i].seg[j].bit_start=keydef[i].seg[j].bit_end=0; - keydef[i].seg[j].language = field->charset()->number; - - if (field->null_ptr) - { - keydef[i].seg[j].null_bit=field->null_bit; - keydef[i].seg[j].null_pos= (uint) (field->null_ptr- - (uchar*) table_arg->record[0]); - } - else - { - keydef[i].seg[j].null_bit=0; - keydef[i].seg[j].null_pos=0; - } - if (field->type() == FIELD_TYPE_BLOB || - field->type() == FIELD_TYPE_GEOMETRY) - { - keydef[i].seg[j].flag|=HA_BLOB_PART; - /* save number of bytes used to pack length */ - keydef[i].seg[j].bit_start= (uint) (field->pack_length() - - table_arg->blob_ptr_size); - } - } - keyseg+=pos->key_parts; - } - - if (table_arg->found_next_number_field) - { - keydef[table_arg->next_number_index].flag|= HA_AUTO_KEY; - found_real_auto_increment= table_arg->next_number_key_offset == 0; - } - - recpos=0; recinfo_pos=recinfo; - while (recpos < (uint) table_arg->reclength) - { - Field **field,*found=0; - minpos=table_arg->reclength; length=0; - - for (field=table_arg->field ; *field ; field++) - { - if ((fieldpos=(*field)->offset()) >= recpos && - fieldpos <= minpos) - { - /* skip null fields */ - if (!(temp_length= (*field)->pack_length())) - continue; /* Skip null-fields */ - if (! found || fieldpos < minpos || - (fieldpos == minpos && temp_length < length)) - { - minpos=fieldpos; found= *field; length=temp_length; - } - } - } - DBUG_PRINT("loop",("found: %lx recpos: %d minpos: %d length: %d", - found,recpos,minpos,length)); - if (recpos != minpos) - { // Reserved space (Null bits?) - bzero((char*) recinfo_pos,sizeof(*recinfo_pos)); - recinfo_pos->type=(int) FIELD_NORMAL; - recinfo_pos++->length= (uint16) (minpos-recpos); - } - if (! found) - break; - - if (found->flags & BLOB_FLAG) - { - recinfo_pos->type= (int) FIELD_BLOB; - } - else if (!(options & HA_OPTION_PACK_RECORD)) - recinfo_pos->type= (int) FIELD_NORMAL; - else if (found->zero_pack()) - recinfo_pos->type= (int) FIELD_SKIP_ZERO; - else - recinfo_pos->type= (int) ((length <= 3 || - (found->flags & ZEROFILL_FLAG)) ? - FIELD_NORMAL : - found->type() == FIELD_TYPE_STRING || - found->type() == FIELD_TYPE_VAR_STRING ? - FIELD_SKIP_ENDSPACE : - FIELD_SKIP_PRESPACE); - if (found->null_ptr) - { - recinfo_pos->null_bit=found->null_bit; - recinfo_pos->null_pos= (uint) (found->null_ptr- - (uchar*) table_arg->record[0]); - } - else - { - recinfo_pos->null_bit=0; - recinfo_pos->null_pos=0; - } - (recinfo_pos++) ->length=(uint16) length; - recpos=minpos+length; - DBUG_PRINT("loop",("length: %d type: %d", - recinfo_pos[-1].length,recinfo_pos[-1].type)); - - } + MI_COLUMNDEF *recinfo; MI_CREATE_INFO create_info; - bzero((char*) &create_info,sizeof(create_info)); - create_info.max_rows=table_arg->max_rows; - create_info.reloc_rows=table_arg->min_rows; - create_info.with_auto_increment=found_real_auto_increment; - create_info.auto_increment=(info->auto_increment_value ? - info->auto_increment_value -1 : - (ulonglong) 0); + DBUG_ENTER("ha_myisam::create"); + if ((error= table2myisam(table_arg, &keydef, &recinfo, &records))) + DBUG_RETURN(error); /* purecov: inspected */ + bzero((char*) &create_info, sizeof(create_info)); + create_info.max_rows= table_arg->max_rows; + create_info.reloc_rows= table_arg->min_rows; + create_info.with_auto_increment= table_arg->next_number_key_offset == 0; + create_info.auto_increment= (info->auto_increment_value ? + info->auto_increment_value -1 : + (ulonglong) 0); create_info.data_file_length= ((ulonglong) table_arg->max_rows * - table_arg->avg_row_length); - create_info.raid_type=info->raid_type; + table_arg->avg_row_length); + create_info.raid_type= info->raid_type; create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks : - RAID_DEFAULT_CHUNKS); - create_info.raid_chunksize=(info->raid_chunksize ? info->raid_chunksize : - RAID_DEFAULT_CHUNKSIZE); + RAID_DEFAULT_CHUNKS); + create_info.raid_chunksize= (info->raid_chunksize ? info->raid_chunksize : + RAID_DEFAULT_CHUNKSIZE); create_info.data_file_name= info->data_file_name; - create_info.index_file_name=info->index_file_name; + create_info.index_file_name= info->index_file_name; if (info->options & HA_LEX_CREATE_TMP_TABLE) create_flags|= HA_CREATE_TMP_TABLE; @@ -1531,13 +1670,13 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, create_flags|= HA_CREATE_DELAY_KEY_WRITE; /* TODO: Check that the following fn_format is really needed */ - error=mi_create(fn_format(buff,name,"","",2+4), - table_arg->keys,keydef, - (uint) (recinfo_pos-recinfo), recinfo, - 0, (MI_UNIQUEDEF*) 0, - &create_info, create_flags); - - my_free((gptr) recinfo,MYF(0)); + error= mi_create(fn_format(buff, name, "", "", + MY_UNPACK_FILENAME|MY_REPLACE_EXT), + table_arg->keys, keydef, + records, recinfo, + 0, (MI_UNIQUEDEF*) 0, + &create_info, create_flags); + my_free((gptr) recinfo, MYF(0)); DBUG_RETURN(error); } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 1fed5cc35f0..53923add49a 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -32,6 +32,13 @@ ** MyISAM MERGE tables *****************************************************************************/ +extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, + MI_COLUMNDEF **recinfo_out, uint *records_out); +extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, + uint t1_keys, uint t1_recs, + MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo, + uint t2_keys, uint t2_recs, bool strict); + const char **ha_myisammrg::bas_ext() const { static const char *ext[]= { ".MRG", NullS }; return ext; } @@ -49,6 +56,12 @@ const char *ha_myisammrg::index_type(uint key_number) int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) { + MI_KEYDEF *keyinfo; + MI_COLUMNDEF *recinfo; + MYRG_TABLE *u_table; + uint recs; + uint keys= table->keys; + int error; char name_buff[FN_REFLEN]; DBUG_PRINT("info", ("ha_myisammrg::open")); @@ -69,20 +82,45 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) if (table->reclength != mean_rec_length && mean_rec_length) { - DBUG_PRINT("error",("reclength: %d mean_rec_length: %d", + DBUG_PRINT("error",("reclength: %d mean_rec_length: %lu", table->reclength, mean_rec_length)); + error= HA_ERR_WRONG_MRG_TABLE_DEF; goto err; } + if ((error= table2myisam(table, &keyinfo, &recinfo, &recs))) + { + /* purecov: begin inspected */ + DBUG_PRINT("error", ("Failed to convert TABLE object to MyISAM " + "key and column definition")); + goto err; + /* purecov: end */ + } + for (u_table= file->open_tables; u_table < file->end_table; u_table++) + { + if (check_definition(keyinfo, recinfo, keys, recs, + u_table->table->s->keyinfo, u_table->table->s->rec, + u_table->table->s->base.keys, + u_table->table->s->base.fields, false)) + { + my_free((gptr) recinfo, MYF(0)); + error= HA_ERR_WRONG_MRG_TABLE_DEF; + goto err; + } + } + my_free((gptr) recinfo, MYF(0)); #if !defined(BIG_TABLES) || SIZEOF_OFF_T == 4 /* Merge table has more than 2G rows */ if (table->crashed) + { + error= HA_ERR_WRONG_MRG_TABLE_DEF; goto err; + } #endif return (0); err: myrg_close(file); file=0; - return (my_errno= HA_ERR_WRONG_MRG_TABLE_DEF); + return (my_errno= error); } int ha_myisammrg::close(void) From 8233b914ecc3cdc9cbec27aba4406c0ecd67cb58 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 31 Jan 2007 18:32:53 +0400 Subject: [PATCH 6/9] After merge fix (WL#3567). --- sql/ha_myisam.cc | 3 ++- sql/ha_myisammrg.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 18e621142f7..39f8894ae89 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1728,12 +1728,13 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, HA_CREATE_INFO *info) { int error; - uint create_flags= 0, options= table_arg->db_options_in_use, records; + uint create_flags= 0, records; char buff[FN_REFLEN]; MI_KEYDEF *keydef; MI_COLUMNDEF *recinfo; MI_CREATE_INFO create_info; TABLE_SHARE *share= table->s; + uint options= share->db_options_in_use; DBUG_ENTER("ha_myisam::create"); if ((error= table2myisam(table_arg, &keydef, &recinfo, &records))) DBUG_RETURN(error); /* purecov: inspected */ diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 97823e2cf47..8e24164abc9 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -97,7 +97,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) MI_COLUMNDEF *recinfo; MYRG_TABLE *u_table; uint recs; - uint keys= table->keys; + uint keys= table->s->keys; int error; char name_buff[FN_REFLEN]; From 2df292258636d678c1202140cffb75917af9a766 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Feb 2007 18:00:24 +0400 Subject: [PATCH 7/9] Valgrind error fixes Notes: This patch doesn't fix all issues in the tree and we need jani's fix for that This patch shoud not be merged into 5.0 mysql-test/r/ps.result: result fix mysql-test/r/symlink.result: result fix mysql-test/t/ps.test: test is moved to 'symlink' test mysql-test/t/symlink.test: test from 'ps' test sql/field_conv.cc: valgrind error fix: backport from 5.0 sql/mysqld.cc: release of ssl_context vio/viosslfactories.c: release of ssl_context mysql-test/valgrind.supp: New BitKeeper file ``mysql-test/valgrind.supp'' This file is backported from 5.0, added suppressing of OpenSSL errors --- mysql-test/r/ps.result | 15 -- mysql-test/r/symlink.result | 15 ++ mysql-test/t/ps.test | 18 -- mysql-test/t/symlink.test | 19 ++ mysql-test/valgrind.supp | 437 ++++++++++++++++++++++++++++++++++++ sql/field_conv.cc | 4 + sql/mysqld.cc | 3 + vio/viosslfactories.c | 4 + 8 files changed, 482 insertions(+), 33 deletions(-) create mode 100644 mysql-test/valgrind.supp diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 0d6b01f3481..d8a75737efc 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1087,19 +1087,4 @@ t2 CREATE TABLE `t2` ( drop database mysqltest; deallocate prepare stmt1; deallocate prepare stmt2; -execute stmt; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `c` char(10) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' -drop table t1; -execute stmt; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `c` char(10) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' -drop table t1; -deallocate prepare stmt; End of 4.1 tests. diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index bc7d3275754..9b21dc7e952 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -123,4 +123,19 @@ select * from t1; a 42 drop table t1; +execute stmt; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' +drop table t1; +execute stmt; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(10) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' +drop table t1; +deallocate prepare stmt; End of 4.1 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c963e59110f..a0133897f50 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1128,22 +1128,4 @@ drop database mysqltest; deallocate prepare stmt1; deallocate prepare stmt2; # -# CREATE TABLE with DATA DIRECTORY option -# -# Protect ourselves from data left in tmp/ by a previos possibly failed -# test ---system rm -f $MYSQLTEST_VARDIR/tmp/t1.* ---disable_query_log -eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'"; ---enable_query_log -execute stmt; ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -show create table t1; -drop table t1; -execute stmt; ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -show create table t1; -drop table t1; -deallocate prepare stmt; -# --echo End of 4.1 tests. diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 23fd779ee13..010ef496399 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -170,4 +170,23 @@ connection default; select * from t1; drop table t1; +# +# CREATE TABLE with DATA DIRECTORY option +# +# Protect ourselves from data left in tmp/ by a previos possibly failed +# test +--system rm -f $MYSQLTEST_VARDIR/tmp/t1.* +--disable_query_log +eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'"; +--enable_query_log +execute stmt; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +show create table t1; +drop table t1; +execute stmt; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +show create table t1; +drop table t1; +deallocate prepare stmt; + --echo End of 4.1 tests diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp new file mode 100644 index 00000000000..716dca491ce --- /dev/null +++ b/mysql-test/valgrind.supp @@ -0,0 +1,437 @@ +# +# 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* +} + +{ + pthread allocate_tls memory loss + Memcheck:Leak + fun:calloc + fun:_dl_allocate_tls + fun:pthread_create* +} + +{ + 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 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 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 longest_match 3 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:gzclose +} + +{ + libz longest_match 4 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:gzflush +} + +{ + 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 +} + + +# +# 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 +} + +# +# Leaks reported in _dl_* internal functions on Linux amd64 / glibc2.3.2. +# + +{ + _dl_start invalid write8 + Memcheck:Addr8 + fun:_dl_start +} + +{ + _dl_start invalid write4 + Memcheck:Addr4 + fun:_dl_start +} + +{ + _dl_start/_dl_setup_hash invalid read8 + Memcheck:Addr8 + fun:_dl_setup_hash + fun:_dl_start +} + +{ + _dl_sysdep_start invalid write8 + Memcheck:Addr8 + fun:_dl_sysdep_start +} + +{ + _dl_init invalid write8 + Memcheck:Addr8 + fun:_dl_init +} + +{ + _dl_init invalid write4 + Memcheck:Addr4 + fun:_dl_init +} + +{ + _dl_init/_dl_init invalid read8 + Memcheck:Addr8 + fun:_dl_debug_initialize + fun:_dl_init +} + +{ + _dl_init/_dl_debug_state invalid read8 + Memcheck:Addr8 + fun:_dl_debug_state + fun:_dl_init +} + +{ + init invalid write8 + Memcheck:Addr8 + fun:init +} + +{ + fixup invalid write8 + Memcheck:Addr8 + fun:fixup +} + +{ + fixup/_dl_lookup_versioned_symbol invalid read8 + Memcheck:Addr8 + fun:_dl_lookup_versioned_symbol + fun:fixup +} + +{ + _dl_runtime_resolve invalid read8 + Memcheck:Addr8 + fun:_dl_runtime_resolve +} + +{ + __libc_start_main invalid write8 + Memcheck:Addr8 + fun:__libc_start_main +} + +{ + __libc_start_main/__sigjmp_save invalid write4 + Memcheck:Addr4 + fun:__sigjmp_save + fun:__libc_start_main +} + +# +# These seem to be libc threading stuff, not related to MySQL code (allocations +# during pthread_exit()). Googling shows other projects also using these +# suppressions. +# +# Note that these all stem from pthread_exit() deeper in the call stack, but +# Valgrind only allows the top four calls in the suppressions. +# + +{ + libc pthread_exit 1 + Memcheck:Leak + fun:malloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + libc pthread_exit 2 + Memcheck:Leak + fun:malloc + fun:_dl_map_object + fun:dl_open_worker + fun:_dl_catch_error +} + +{ + libc pthread_exit 3 + Memcheck:Leak + fun:malloc + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error +} + +{ + libc pthread_exit 4 + Memcheck:Leak + fun:calloc + fun:_dl_check_map_versions + fun:dl_open_worker + fun:_dl_catch_error +} + +{ + libc pthread_exit 5 + Memcheck:Leak + fun:calloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + + + +# +# This is seen internally in the system libraries on 64-bit RHAS3. +# + +{ + __lll_mutex_unlock_wake uninitialized + Memcheck:Param + futex(utime) + fun:__lll_mutex_unlock_wake +} + +# +# BUG#19940: NDB sends uninitialized parts of field buffers across the wire. +# This is "works as designed"; the uninitialized part is not used at the +# other end (but Valgrind cannot see this). +# +{ + bug19940 + Memcheck:Param + socketcall.sendto(msg) + fun:send + fun:_ZN15TCP_Transporter6doSendEv + fun:_ZN19TransporterRegistry11performSendEv + fun:_ZN19TransporterRegistry14forceSendCheckEi +} + +{ + OpenSSL_1 + Memcheck:Cond + fun:BN_num_bits_word + fun:BN_num_bits + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:*libcrypto.so.* + obj:*libcrypto.so.* + fun:DH_generate_key + fun:ssl3_ctx_ctrl + fun:SSL_CTX_ctrl + fun:new_VioSSLAcceptorFd + fun:main +} + +{ + OpenSSL_2 + Memcheck:Value4 + fun:BN_num_bits_word + fun:BN_num_bits + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:*libcrypto.so.* + obj:*libcrypto.so.* + fun:DH_generate_key + fun:ssl3_ctx_ctrl + fun:SSL_CTX_ctrl + fun:new_VioSSLAcceptorFd + fun:main +} + +{ + OpenSSL_3 + Memcheck:Value4 + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:*libcrypto.so.* + obj:*libcrypto.so.* + fun:DH_generate_key + fun:ssl3_ctx_ctrl + fun:SSL_CTX_ctrl + fun:new_VioSSLAcceptorFd + fun:main +} + +{ + OpenSSL_4 + Memcheck:Cond + fun:BN_bin2bn + obj:*libcrypto.so.* + obj:*libcrypto.so.* + fun:DH_generate_key + fun:ssl3_ctx_ctrl + fun:SSL_CTX_ctrl + fun:new_VioSSLAcceptorFd + fun:main +} + +{ + OpenSSL_5 + Memcheck:Leak + fun:realloc + obj:*libcrypto.so.* + fun:CRYPTO_realloc + fun:lh_insert + fun:OBJ_NAME_add + fun:EVP_add_cipher + fun:OpenSSL_add_all_ciphers + fun:OPENSSL_add_all_algorithms_noconf + fun:new_VioSSLAcceptorFd + fun:main +} + +{ + OpenSSL_6 + Memcheck:Leak + fun:malloc + obj:*libcrypto.so.* + fun:CRYPTO_malloc + fun:lh_new + fun:OBJ_NAME_init + fun:OBJ_NAME_add + fun:EVP_add_cipher + fun:SSL_library_init + fun:new_VioSSLAcceptorFd + fun:main +} diff --git a/sql/field_conv.cc b/sql/field_conv.cc index d61b3735c91..59b550572c3 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -605,6 +605,10 @@ void field_conv(Field *to,Field *from) from->charset() == to->charset() && to->table->db_low_byte_first == from->table->db_low_byte_first) { // Identical fields +#ifdef HAVE_purify + /* This may happen if one does 'UPDATE ... SET x=x' */ + if (to->ptr != from->ptr) +#endif memcpy(to->ptr,from->ptr,to->pack_length()); return; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d9962eec4c1..0cccf097132 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1070,7 +1070,10 @@ void clean_up(bool print_message) #endif #ifdef HAVE_OPENSSL if (ssl_acceptor_fd) + { + SSL_CTX_free(ssl_acceptor_fd->ssl_context); my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR)); + } #endif /* HAVE_OPENSSL */ #ifdef USE_REGEX my_regex_end(); diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 46306cf48bb..1ac5d96d158 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -289,6 +289,8 @@ new_VioSSLConnectorFd(const char* key_file, DBUG_RETURN(ptr); ctor_failure: DBUG_PRINT("exit", ("there was an error")); + if (ptr->ssl_context) + SSL_CTX_free(ptr->ssl_context); my_free((gptr)ptr,MYF(0)); DBUG_RETURN(0); } @@ -390,6 +392,8 @@ new_VioSSLAcceptorFd(const char *key_file, ctor_failure: DBUG_PRINT("exit", ("there was an error")); + if (ptr->ssl_context) + SSL_CTX_free(ptr->ssl_context); my_free((gptr) ptr,MYF(0)); DBUG_RETURN(0); } From 8c2c52714d31dccbd0f5734e0a8e7de48c7e36b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Feb 2007 15:59:51 +0100 Subject: [PATCH 8/9] Bug#25844: "make test" does not find mysql-test-run.pl Need to change directory before calling mysql-test-run.pl --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 798d1944fd0..04d50ccfbaf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -123,6 +123,7 @@ tags: # making sure each user use different ports. test-ps: + cd mysql-test ; \ @PERL@ ./mysql-test-run.pl $(force) --ps-protocol test-ns: From 5305cd7caf74919b1da4413a9923da1c0ff00734 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Feb 2007 10:01:44 +0100 Subject: [PATCH 9/9] After merge fix --- include/my_pthread.h | 1 - include/thr_alarm.h | 1 + mysys/my_pthread.c | 3 --- mysys/my_thr_init.c | 4 ---- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 3bcb30cd1f1..14dbc9825d4 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -683,7 +683,6 @@ extern pthread_t shutdown_th, main_th, signal_th; #define THD_LIB_LT 4 extern uint thd_lib_detected; -extern uint thr_client_alarm; /* statistics_xxx functions are for not essential statistic */ diff --git a/include/thr_alarm.h b/include/thr_alarm.h index ef6aaf49f77..1d7ebbcb9f5 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -94,6 +94,7 @@ typedef struct st_alarm { } ALARM; extern uint thr_client_alarm; +extern pthread_t alarm_thread; #define thr_alarm_init(A) (*(A))=0 #define thr_alarm_in_use(A) (*(A)!= 0) diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 09685ba3e12..14ba6aabf0e 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -31,7 +31,6 @@ #endif uint thd_lib_detected; -uint thr_client_alarm; #ifndef my_pthread_setprio void my_pthread_setprio(pthread_t thread_id,int prior) @@ -319,8 +318,6 @@ void sigwait_handle_sig(int sig) pthread_mutex_unlock(&LOCK_sigwait); } -extern pthread_t alarm_thread; - void *sigwait_thread(void *set_arg) { sigset_t *set=(sigset_t*) set_arg; diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 34fa2e8aa7e..42f025c39f3 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -61,10 +61,6 @@ static uint get_thread_lib(void); my_bool my_thread_global_init(void) { thd_lib_detected= get_thread_lib(); - if (thd_lib_detected == THD_LIB_LT) - thr_client_alarm= SIGALRM; - else - thr_client_alarm= SIGUSR1; if (pthread_key_create(&THR_KEY_mysys,0)) {