From a437b82affd3323bd02dc60ae0b4565825f1418d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Apr 2005 14:44:54 +0500 Subject: [PATCH 1/7] A fix (bug #9837: round(1, 6) delivers wrong value in create table context). sql/item_func.cc: A fix (bug #9837: round(1, 6) delivers wrong value in create table context). As we change decimals, we should change max_length accordingly. --- mysql-test/r/func_math.result | 11 +++++++++++ mysql-test/t/func_math.test | 13 +++++++++++++ sql/item_func.cc | 2 ++ 3 files changed, 26 insertions(+) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 3a28cccfac5..9cb1e4a56d6 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -1,3 +1,4 @@ +drop table if exists t1; select floor(5.5),floor(-5.5); floor(5.5) floor(-5.5) 5 -6 @@ -126,3 +127,13 @@ Warnings: Note 1003 select degrees(pi()) AS `degrees(pi())`,radians(360) AS `radians(360)` select rand(rand); ERROR 42S22: Unknown column 'rand' in 'field list' +create table t1 select round(1, 6); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `round(1, 6)` double(7,6) NOT NULL default '0.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from t1; +round(1, 6) +1.000000 +drop table t1; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 668aefc2d8d..4c24dae8c5d 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -2,6 +2,10 @@ # Test of math functions # +--disable_warnings +drop table if exists t1; +--enable_warnings + select floor(5.5),floor(-5.5); explain extended select floor(5.5),floor(-5.5); select ceiling(5.5),ceiling(-5.5); @@ -58,3 +62,12 @@ explain extended select degrees(pi()),radians(360); --error 1054 select rand(rand); + +# +# Bug #9837: problem with round() +# + +create table t1 select round(1, 6); +show create table t1; +select * from t1; +drop table t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index eb6e395c266..2b38584fe23 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1072,6 +1072,8 @@ void Item_func_round::fix_length_and_dec() decimals=0; else decimals=min(tmp,NOT_FIXED_DEC); + if ((tmp= decimals - args[0]->decimals) > 0) + max_length+= tmp; } } From 677fbc7d4e34dff14aaf49efa114bc85aa986da1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Apr 2005 20:10:28 +0200 Subject: [PATCH 2/7] Step 1 of the switch to support configuration with NPTL: Rename 'IS_LINUX' configuration variable to 'TARGET_LINUX'. --- acinclude.m4 | 2 +- configure.in | 18 +++++++++--------- myisam/Makefile.am | 2 +- scripts/Makefile.am | 2 +- scripts/mysqld_safe.sh | 2 +- support-files/Makefile.am | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 74426bc2061..a81a4fa5c3f 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -976,7 +976,7 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then echo "Could not find an installation of OpenSSL" if test -n "$OPENSSL_LIB" ; then - if test "$IS_LINUX" = "true"; then + if test "$TARGET_LINUX" = "true"; then echo "Looks like you've forgotten to install OpenSSL development RPM" fi fi diff --git a/configure.in b/configure.in index d191463d0f9..6650c0fc64a 100644 --- a/configure.in +++ b/configure.in @@ -410,15 +410,15 @@ 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"); 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) @@ -607,7 +607,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" @@ -841,7 +841,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]) atom_ops= @@ -885,7 +885,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" @@ -1286,7 +1286,7 @@ then else AC_MSG_RESULT("Not found") # If this is a linux machine we should barf - if test "$IS_LINUX" = "true" + if test "$TARGET_LINUX" = "true" then AC_MSG_ERROR([This is a linux system and Linuxthreads was not found. On linux Linuxthreads should be used. Please install Linuxthreads @@ -1738,7 +1738,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") @@ -1955,7 +1955,7 @@ CFLAGS="$ORG_CFLAGS" # Sanity check: We chould not have any fseeko symbol unless # large_file_support=yes AC_CHECK_FUNC(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/myisam/Makefile.am b/myisam/Makefile.am index 378e8107814..0b8a25e3404 100644 --- a/myisam/Makefile.am +++ b/myisam/Makefile.am @@ -88,7 +88,7 @@ SUFFIXES = .sh -e 's!@''FIND_PROC''@!@FIND_PROC@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ - -e 's!@''IS_LINUX''@!@IS_LINUX@!' \ + -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''sysconfdir''@!@sysconfdir@!' \ diff --git a/scripts/Makefile.am b/scripts/Makefile.am index b170fa483b2..e2ef1bba97c 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -135,7 +135,7 @@ SUFFIXES = .sh -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \ - -e 's!@''IS_LINUX''@!@IS_LINUX@!' \ + -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''STATIC_NSS_FLAGS''@!@STATIC_NSS_FLAGS@!' \ diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 308db270828..8a232f4f7f9 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -324,7 +324,7 @@ do break fi - if @IS_LINUX@ && test $KILL_MYSQLD -eq 1 + if @TARGET_LINUX@ && test $KILL_MYSQLD -eq 1 then # Test if one process was hanging. # This is only a fix for Linux (running as base 3 mysqld processes) diff --git a/support-files/Makefile.am b/support-files/Makefile.am index 0a6077f0efc..5f5a10fc1fc 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -90,7 +90,7 @@ SUFFIXES = .sh -e 's!@''FIND_PROC''@!@FIND_PROC@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ - -e 's!@''IS_LINUX''@!@IS_LINUX@!' \ + -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''sysconfdir''@!@sysconfdir@!' \ From b6a4a2f41cb7aa04b59d8017070a69cd6f4c5082 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Apr 2005 20:38:57 +0200 Subject: [PATCH 3/7] Step 2 of the switch to support configuration with NPTL: Define a new CPP symbol that the target OS is Linux, and use it where only the OS matters and not the threads Library. Until now, 'HAVE_LINUXTHREADS' was used to indicate "Target is Linux" in many places. When we support configuration with NPTL but no Linuxthreads, this misuse must cease. configure.in: Step 2 of the switch to support configuration with NPTL: Define a new CPP symbol that the target OS is Linux. Until now, 'HAVE_LINUXTHREADS' was used to indicate "Target is Linux" in many places. When we support configuration with NPTL but no Linuxthreads, this misuse must cease. include/my_global.h: Step 2 of the switch to support configuration with NPTL: Use the new 'TARGET_OS_LINUX' where only the OS matters and not the threads Library. mysys/thr_mutex.c: Step 2 of the switch to support configuration with NPTL: Use the new 'TARGET_OS_LINUX' where only the OS matters and not the threads Library. sql/stacktrace.c: Step 2 of the switch to support configuration with NPTL: Use the new 'TARGET_OS_LINUX' where only the OS matters and not the threads Library. sql/stacktrace.h: Step 2 of the switch to support configuration with NPTL: Use the new 'TARGET_OS_LINUX' where only the OS matters and not the threads Library. tools/mysqlmanager.c: Step 2 of the switch to support configuration with NPTL: Use the new 'TARGET_OS_LINUX' where only the OS matters and not the threads Library. --- configure.in | 1 + include/my_global.h | 8 ++++---- mysys/thr_mutex.c | 2 +- sql/stacktrace.c | 4 ++-- sql/stacktrace.h | 4 ++-- tools/mysqlmanager.c | 2 +- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/configure.in b/configure.in index 6650c0fc64a..f7a266eebec 100644 --- a/configure.in +++ b/configure.in @@ -412,6 +412,7 @@ then MYSQLD_DEFAULT_SWITCHES="--skip-locking" TARGET_LINUX="true" AC_MSG_RESULT("yes"); + AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux]) else MYSQLD_DEFAULT_SWITCHES="" TARGET_LINUX="false" diff --git a/include/my_global.h b/include/my_global.h index 23cf0d54824..a027bf9d2bb 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) #undef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -214,13 +214,13 @@ C_MODE_START int __cxa_pure_virtual() {\ #endif /* In Linux-alpha we have atomic.h if we are using gcc */ -#if defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD) +#if defined(TARGET_OS_LINUX) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD) #define HAVE_ATOMIC_ADD #define HAVE_ATOMIC_SUB #endif /* In Linux-ia64 including atomic.h will give us an error */ -#if (defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD) +#if (defined(TARGET_OS_LINUX) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD) #undef HAVE_ATOMIC_ADD #undef HAVE_ATOMIC_SUB #endif @@ -755,7 +755,7 @@ typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */ error "Neither int or long is of 4 bytes width" #endif -#if !defined(HAVE_ULONG) && !defined(HAVE_LINUXTHREADS) && !defined(__USE_MISC) +#if !defined(HAVE_ULONG) && !defined(TARGET_OS_LINUX) && !defined(__USE_MISC) typedef unsigned long ulong; /* Short for unsigned long */ #endif #ifndef longlong_defined diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index bbcfaa8bba6..2facb4e18cf 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -17,7 +17,7 @@ /* This makes a wrapper for mutex handling to make it easier to debug mutex */ #include -#if defined(HAVE_LINUXTHREADS) && !defined (__USE_UNIX98) +#if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98) #define __USE_UNIX98 /* To get rw locks under Linux */ #endif #if defined(THREAD) && defined(SAFE_MUTEX) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 322d647e741..838f547dc02 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -43,7 +43,7 @@ void safe_print_str(const char* name, const char* val, int max_len) fputc('\n', stderr); } -#ifdef HAVE_LINUXTHREADS +#ifdef TARGET_OS_LINUX #define SIGRETURN_FRAME_COUNT 2 #if defined(__alpha__) && defined(__GNUC__) @@ -201,7 +201,7 @@ end: stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } -#endif /* HAVE_LINUXTHREADS */ +#endif /* TARGET_OS_LINUX */ #endif /* HAVE_STACKTRACE */ /* Produce a core for the thread */ diff --git a/sql/stacktrace.h b/sql/stacktrace.h index 980e1ea07eb..d5d1e05ef0e 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -18,7 +18,7 @@ extern "C" { #endif -#ifdef HAVE_LINUXTHREADS +#ifdef TARGET_OS_LINUX #if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE #define HAVE_STACKTRACE @@ -30,7 +30,7 @@ extern char* heap_start; void print_stacktrace(gptr stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ -#endif /* HAVE_LINUXTHREADS */ +#endif /* TARGET_OS_LINUX */ /* Define empty prototypes for functions that are not implemented */ #ifndef HAVE_STACKTRACE diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c index bb0a76d6c49..27caa1e0255 100644 --- a/tools/mysqlmanager.c +++ b/tools/mysqlmanager.c @@ -101,7 +101,7 @@ static CHARSET_INFO *cs= &my_charset_latin1; set by the user */ -#if defined(__i386__) && defined(HAVE_LINUXTHREADS) +#if defined(__i386__) && defined(TARGET_OS_LINUX) #define DO_STACKTRACE 1 #endif From 8a9c988122135441d35bbab1b70c3e0ccb88b7a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Apr 2005 20:49:05 +0200 Subject: [PATCH 4/7] Step 3 of the switch to support configuration with NPTL: Change "configure.in". The branches for Tru64 (ex: OSF/1) and Linux are separated, and for Linux 'getconf GNU_LIBPTHREAD_VERSION' is used to tell between Linuxthreads and NPTL. configure.in: Step 3 of the switch to support configuration with NPTL: Change "configure.in". 1) Separate the branches checking for thread libraries on OSF/1 (now: Tru64) and on Linux, as these are different things. In the Tru64 branch, remove the obsolete part for OSF/1 3.2, because that is gone since long (about a decade?); we are at 5 now. Adapt the comment. 2) For Linux, the thread libraries are "Linuxthreads" (older) and "NPTL" (newer). Until now, we cared only about "Linuxthreads", and we did so by checking a comment in the header file '/usr/include/pthread.h'. With NPTL as an alternative or only thread package, this is not secure any more, there are distributions where the header file still contains that comment but the lib is NPTL. For all current distributions, the way to check is the 'getconf' command. On old distributions, 'getconf' exists but does not understand the 'GNU_LIBPTHREAD_VERSION' parameter. It is unlikely that such an old system should have NPTL, so the header file check is sufficient if the getconf inquiry fails. For both Linuxthreads and NPTL, '-lpthread' is the linker option to use. 3) To detect problems as early as possible, on Linux a link test using '-lpthread' is done. The code is copied from a later check where the thread functions are searched in '-lc', '-lpthread', and '-lpthreads', but this later search would not be executed after the lib was already determined. So if the test is not done here, it will be detected only during the real build. This is too late. --- configure.in | 138 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 53 deletions(-) diff --git a/configure.in b/configure.in index f7a266eebec..dfffecdff08 100644 --- a/configure.in +++ b/configure.in @@ -411,12 +411,12 @@ if expr "$target_os" : "[[Ll]]inux.*" > /dev/null then MYSQLD_DEFAULT_SWITCHES="--skip-locking" TARGET_LINUX="true" - AC_MSG_RESULT("yes"); + AC_MSG_RESULT("yes") AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux]) else MYSQLD_DEFAULT_SWITCHES="" TARGET_LINUX="false" - AC_MSG_RESULT("no"); + AC_MSG_RESULT("no") fi AC_SUBST(MYSQLD_DEFAULT_SWITCHES) AC_SUBST(TARGET_LINUX) @@ -1267,61 +1267,93 @@ esac # We have to check libc last because else it fails on Solaris 2.6 with_posix_threads="no" -# Hack for DEC-UNIX (OSF1) +# Search thread lib on Linux if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" then - # Look for LinuxThreads. - AC_MSG_CHECKING("LinuxThreads") - res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l` - if test "$res" -gt 0 + AC_MSG_CHECKING("Linux threads") + if test "$TARGET_LINUX" = "true" 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 - if test "$TARGET_LINUX" = "true" - then - AC_MSG_ERROR([This is a linux system and Linuxthreads was not -found. On linux Linuxthreads should be used. Please install Linuxthreads -(or a new glibc) and try again. See the Installation chapter in the -Reference Manual for more information.]) - 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, [1], - [Whether we are using 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, [1]) - AC_DEFINE([HAVE_DEC_3_2_THREADS], [1], - [Whether we are using OSF1 DEC threads on 3.2]) - with_osf32_threads="yes" - MYSQLD_DEFAULT_SWITCHES="--skip-thread-priority" - AC_MSG_RESULT("yes") - else - AC_MSG_RESULT("no") + 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 + # 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 -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" + + +# Hack for DEC-UNIX (OSF1 -> Tru64) +if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" +then + AC_MSG_CHECKING("DEC threads post OSF/1 3.2") + 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, [1], [Whether we are using DEC threads]) + AC_MSG_RESULT("yes") + else + AC_MSG_RESULT("no") + fi # DEC threads +fi # "$with_named_thread" = "no" -a "$with_mit_threads" = "no" dnl This is needed because -lsocket has to come after the thread From 910c30586773c57f70ed5e12a3795de5b890071d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Apr 2005 13:15:20 +0200 Subject: [PATCH 5/7] Final fix for NPTL configuration (bug#2173, bug#5871, and bug#9497). include/my_global.h: As we have a new CPP symbol, this should be "undef"ed explicitly. --- include/my_global.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/my_global.h b/include/my_global.h index a027bf9d2bb..745179e8a06 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -107,6 +107,7 @@ #undef THREAD #undef HAVE_mit_thread #undef HAVE_LINUXTHREADS +#undef HAVE_NPTL #undef HAVE_UNIXWARE7_THREADS #endif From f63c8f53b050016c6be6a152ea01b4e17e9ee071 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Apr 2005 12:40:37 +0200 Subject: [PATCH 6/7] Bug#7823 - FLUSH TABLES WITH READ LOCK + INSERT DELAYED = deadlock Added protection against global read lock while creating and initializing a delayed insert handler. Allowed to ignore a global read lock when locking the table inside the delayed insert handler. Added some minor improvements. sql/lock.cc: Bug#7823 - FLUSH TABLES WITH READ LOCK + INSERT DELAYED = deadlock Changed mysql_lock_tables() to allow for ignoring global read lock. Added functions to set/unset protection against global read lock. sql/mysql_priv.h: Bug#7823 - FLUSH TABLES WITH READ LOCK + INSERT DELAYED = deadlock Changed existing and added new function declarations. sql/sql_insert.cc: Bug#7823 - FLUSH TABLES WITH READ LOCK + INSERT DELAYED = deadlock Added and extended some comments. Added a protection against global read lock while a handler is created and initialized. Moved the unlock of the delayed insert object past its last usage in delayed_get_table(). Changed the table locking in handle_delayed_insert() so that it does not wait for global read lock. --- sql/lock.cc | 51 ++++++++++++++++++++++++++++++-- sql/mysql_priv.h | 5 +++- sql/sql_insert.cc | 75 ++++++++++++++++++++++++++++++++++------------- 3 files changed, 108 insertions(+), 23 deletions(-) diff --git a/sql/lock.cc b/sql/lock.cc index c7e6ebfda83..951b0e2ff6a 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -79,7 +79,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count); static void print_lock_error(int error); -MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) +MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, + bool ignore_global_read_lock) { MYSQL_LOCK *sql_lock; TABLE *write_lock_used; @@ -90,7 +91,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) if (!(sql_lock = get_lock_data(thd,tables,count, 0,&write_lock_used))) break; - if (global_read_lock && write_lock_used) + if (global_read_lock && write_lock_used && ! ignore_global_read_lock) { /* Someone has issued LOCK ALL TABLES FOR READ and we want a write lock @@ -865,3 +866,49 @@ void make_global_read_lock_block_commit(THD *thd) pthread_mutex_unlock(&LOCK_open); thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT; } + + +/* + Set protection against global read lock. + + SYNOPSIS + set_protect_against_global_read_lock() + void + + RETURN + FALSE OK, no global read lock exists. + TRUE Error, global read lock exists already. +*/ + +my_bool set_protect_against_global_read_lock(void) +{ + my_bool global_read_lock_exists; + + pthread_mutex_lock(&LOCK_open); + if (! (global_read_lock_exists= test(global_read_lock))) + protect_against_global_read_lock++; + pthread_mutex_unlock(&LOCK_open); + return global_read_lock_exists; +} + + +/* + Unset protection against global read lock. + + SYNOPSIS + unset_protect_against_global_read_lock() + void + + RETURN + void +*/ + +void unset_protect_against_global_read_lock(void) +{ + pthread_mutex_lock(&LOCK_open); + protect_against_global_read_lock--; + pthread_mutex_unlock(&LOCK_open); + pthread_cond_broadcast(&COND_refresh); +} + + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6281b64bc5e..6a25536b3f1 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -766,7 +766,8 @@ extern pthread_t signal_thread; extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ -MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **table,uint count); +MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, + bool ignore_global_read_lock= FALSE); void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); @@ -779,6 +780,8 @@ void unlock_global_read_lock(THD *thd); bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit); void start_waiting_global_read_lock(THD *thd); void make_global_read_lock_block_commit(THD *thd); +my_bool set_protect_against_global_read_lock(void); +void unset_protect_against_global_read_lock(void); /* Lock based on name */ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0c62a9af7ba..c6b7b1d6c15 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -647,27 +647,42 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) { int error; delayed_insert *tmp; + TABLE *table; DBUG_ENTER("delayed_get_table"); if (!table_list->db) table_list->db=thd->db; - /* no match; create a new thread to handle the table */ + /* Find the thread which handles this table. */ if (!(tmp=find_handler(thd,table_list))) { - /* Don't create more than max_insert_delayed_threads */ + /* + No match. Create a new thread to handle the table, but + no more than max_insert_delayed_threads. + */ if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) DBUG_RETURN(0); thd->proc_info="Creating delayed handler"; pthread_mutex_lock(&LOCK_delayed_create); - if (!(tmp=find_handler(thd,table_list))) // Was just created + /* + The first search above was done without LOCK_delayed_create. + Another thread might have created the handler in between. Search again. + */ + if (! (tmp= find_handler(thd, table_list))) { + /* + Avoid that a global read lock steps in while we are creating the + new thread. It would block trying to open the table. Hence, the + DI thread and this thread would wait until after the global + readlock is gone. If the read lock exists already, we leave with + no table and then switch to non-delayed insert. + */ + if (set_protect_against_global_read_lock()) + goto err; if (!(tmp=new delayed_insert())) { - thd->fatal_error=1; my_error(ER_OUTOFMEMORY,MYF(0),sizeof(delayed_insert)); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); + goto err1; } pthread_mutex_lock(&LOCK_thread_count); thread_count++; @@ -676,10 +691,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME)))) { delete tmp; - thd->fatal_error=1; my_error(ER_OUT_OF_RESOURCES,MYF(0)); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); + goto err1; } tmp->table_list= *table_list; // Needed to open table tmp->table_list.db= tmp->thd.db; @@ -695,10 +708,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) pthread_mutex_unlock(&tmp->mutex); tmp->unlock(); delete tmp; - thd->fatal_error=1; - pthread_mutex_unlock(&LOCK_delayed_create); net_printf(&thd->net,ER_CANT_CREATE_THREAD,error); - DBUG_RETURN(0); + goto err1; } /* Wait until table is open */ @@ -708,6 +719,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) pthread_cond_wait(&tmp->cond_client,&tmp->mutex); } pthread_mutex_unlock(&tmp->mutex); + unset_protect_against_global_read_lock(); thd->proc_info="got old table"; if (tmp->thd.killed) { @@ -719,28 +731,34 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) thd->net.last_errno=tmp->thd.net.last_errno; } tmp->unlock(); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); // Continue with normal insert + goto err; } if (thd->killed) { tmp->unlock(); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); + goto err; } } pthread_mutex_unlock(&LOCK_delayed_create); } pthread_mutex_lock(&tmp->mutex); - TABLE *table=tmp->get_local_table(thd); + table= tmp->get_local_table(thd); pthread_mutex_unlock(&tmp->mutex); - tmp->unlock(); if (table) thd->di=tmp; else if (tmp->thd.fatal_error) thd->fatal_error=1; + /* Unlock the delayed insert object after its last access. */ + tmp->unlock(); DBUG_RETURN((table_list->table=table)); + + err1: + thd->fatal_error= 1; + unset_protect_against_global_read_lock(); + err: + pthread_mutex_unlock(&LOCK_delayed_create); + DBUG_RETURN(0); // Continue with normal insert } @@ -955,6 +973,14 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) thd->killed=abort_loop; pthread_mutex_unlock(&LOCK_thread_count); + /* + Wait until the client runs into pthread_cond_wait(), + where we free it after the table is opened and di linked in the list. + If we did not wait here, the client might detect the opened table + before it is linked to the list. It would release LOCK_delayed_create + and allow another thread to create another handler for the same table, + since it does not find one in the list. + */ pthread_mutex_lock(&di->mutex); #if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */ if (my_thread_init()) @@ -1069,8 +1095,17 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) if (di->tables_in_use && ! thd->lock) { - /* request for new delayed insert */ - if (!(thd->lock=mysql_lock_tables(thd,&di->table,1))) + /* + Request for new delayed insert. + Lock the table, but avoid to be blocked by a global read lock. + If we got here while a global read lock exists, then one or more + inserts started before the lock was requested. These are allowed + to complete their work before the server returns control to the + client which requested the global read lock. The delayed insert + handler will close the table and finish when the outstanding + inserts are done. + */ + if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, TRUE))) { di->dead=thd->killed=1; // Fatal error } From 3238612840467f6edc8aab676f31940fc731bff7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Apr 2005 20:54:19 +0200 Subject: [PATCH 7/7] Bug#7823 - FLUSH TABLES WITH READ LOCK + INSERT DELAYED = deadlock After merge fix. --- sql/sql_insert.cc | 75 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 20 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7f890a583c6..31393b2173a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -851,27 +851,42 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) { int error; delayed_insert *tmp; + TABLE *table; DBUG_ENTER("delayed_get_table"); if (!table_list->db) table_list->db=thd->db; - /* no match; create a new thread to handle the table */ + /* Find the thread which handles this table. */ if (!(tmp=find_handler(thd,table_list))) { - /* Don't create more than max_insert_delayed_threads */ + /* + No match. Create a new thread to handle the table, but + no more than max_insert_delayed_threads. + */ if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) DBUG_RETURN(0); thd->proc_info="Creating delayed handler"; pthread_mutex_lock(&LOCK_delayed_create); - if (!(tmp=find_handler(thd,table_list))) // Was just created + /* + The first search above was done without LOCK_delayed_create. + Another thread might have created the handler in between. Search again. + */ + if (! (tmp= find_handler(thd, table_list))) { + /* + Avoid that a global read lock steps in while we are creating the + new thread. It would block trying to open the table. Hence, the + DI thread and this thread would wait until after the global + readlock is gone. If the read lock exists already, we leave with + no table and then switch to non-delayed insert. + */ + if (set_protect_against_global_read_lock()) + goto err; if (!(tmp=new delayed_insert())) { - thd->fatal_error(); my_error(ER_OUTOFMEMORY,MYF(0),sizeof(delayed_insert)); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); + goto err1; } pthread_mutex_lock(&LOCK_thread_count); thread_count++; @@ -880,10 +895,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME)))) { delete tmp; - thd->fatal_error(); my_error(ER_OUT_OF_RESOURCES,MYF(0)); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); + goto err1; } tmp->table_list= *table_list; // Needed to open table tmp->table_list.db= tmp->thd.db; @@ -899,10 +912,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) pthread_mutex_unlock(&tmp->mutex); tmp->unlock(); delete tmp; - thd->fatal_error(); - pthread_mutex_unlock(&LOCK_delayed_create); net_printf(thd,ER_CANT_CREATE_THREAD,error); - DBUG_RETURN(0); + goto err1; } /* Wait until table is open */ @@ -912,6 +923,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) pthread_cond_wait(&tmp->cond_client,&tmp->mutex); } pthread_mutex_unlock(&tmp->mutex); + unset_protect_against_global_read_lock(); thd->proc_info="got old table"; if (tmp->thd.killed) { @@ -923,28 +935,34 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) thd->net.last_errno=tmp->thd.net.last_errno; } tmp->unlock(); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); // Continue with normal insert + goto err; } if (thd->killed) { tmp->unlock(); - pthread_mutex_unlock(&LOCK_delayed_create); - DBUG_RETURN(0); + goto err; } } pthread_mutex_unlock(&LOCK_delayed_create); } pthread_mutex_lock(&tmp->mutex); - TABLE *table=tmp->get_local_table(thd); + table=tmp->get_local_table(thd); pthread_mutex_unlock(&tmp->mutex); - tmp->unlock(); if (table) thd->di=tmp; else if (tmp->thd.is_fatal_error) thd->fatal_error(); + /* Unlock the delayed insert object after its last access. */ + tmp->unlock(); DBUG_RETURN((table_list->table=table)); + + err1: + thd->fatal_error(); + unset_protect_against_global_read_lock(); + err: + pthread_mutex_unlock(&LOCK_delayed_create); + DBUG_RETURN(0); // Continue with normal insert } @@ -1165,6 +1183,14 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) thd->killed=abort_loop; pthread_mutex_unlock(&LOCK_thread_count); + /* + Wait until the client runs into pthread_cond_wait(), + where we free it after the table is opened and di linked in the list. + If we did not wait here, the client might detect the opened table + before it is linked to the list. It would release LOCK_delayed_create + and allow another thread to create another handler for the same table, + since it does not find one in the list. + */ pthread_mutex_lock(&di->mutex); #if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */ if (my_thread_init()) @@ -1279,8 +1305,17 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) if (di->tables_in_use && ! thd->lock) { - /* request for new delayed insert */ - if (!(thd->lock=mysql_lock_tables(thd,&di->table,1))) + /* + Request for new delayed insert. + Lock the table, but avoid to be blocked by a global read lock. + If we got here while a global read lock exists, then one or more + inserts started before the lock was requested. These are allowed + to complete their work before the server returns control to the + client which requested the global read lock. The delayed insert + handler will close the table and finish when the outstanding + inserts are done. + */ + if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, TRUE))) { di->dead= 1; // Some fatal error thd->killed= 1;