From af2808859e7a98666785752b8069c473dda94a1f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 15 Jun 2012 11:16:44 +0200 Subject: Add support for building against libmysqlclient that lacks THR_KEY_mysys In certain distributions (specifically Fedora 15 and later), maintainers limit the number of visible symbols. If THR_KEY_mysys is hidden, then we try to create the TLS keys in such an order that it results in the correct behavior. And then hope for the best. --- configure.ac | 4 ++++ m4/libmysqlclient.m4 | 22 ++++++++++++++++++++++ odb/mysql/connection-factory.cxx | 37 ++++++++++++++++++++++++------------- odb/mysql/details/config.h.in | 2 ++ odb/mysql/makefile | 1 + 5 files changed, 53 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 01cf652..0902700 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,10 @@ case $libmysqlclient_include in ;; esac +if test x"$libmysqlclient_thr_key_visible" = xyes; then + AC_DEFINE([LIBODB_MYSQL_THR_KEY_VISIBLE], [1], ["THR_KEY_mysys is visible."]) +fi + # Check for libodb. # LIBODB([],[AC_MSG_ERROR([libodb is not found; consider using --with-libodb=DIR])]) diff --git a/m4/libmysqlclient.m4 b/m4/libmysqlclient.m4 index e08a08e..84b4471 100644 --- a/m4/libmysqlclient.m4 +++ b/m4/libmysqlclient.m4 @@ -82,4 +82,26 @@ else AC_MSG_RESULT([no]) $3 fi + +# Check if the THR_KEY_mysys pthread key symbol is visible. +# +libmysqlclient_thr_key_visible=no + +if test x"$libmysqlclient_found" = xyes -a x"$1" = xposix; then + +CXX_LIBTOOL_LINK_IFELSE( +AC_LANG_SOURCE([[ +#include +extern pthread_key_t THR_KEY_mysys; +int +main () +{ + return pthread_getspecific (THR_KEY_mysys) != 0; +} +]]), +[ +libmysqlclient_thr_key_visible=yes +]) +fi + ])dnl diff --git a/odb/mysql/connection-factory.cxx b/odb/mysql/connection-factory.cxx index ef3647e..cc23de5 100644 --- a/odb/mysql/connection-factory.cxx +++ b/odb/mysql/connection-factory.cxx @@ -2,21 +2,22 @@ // copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file -#include // ODB_THREADS_* +#include // ODB_THREADS_* +#include // LIBODB_MYSQL_THR_KEY_VISIBLE -#ifdef ODB_THREADS_POSIX +#if defined(ODB_THREADS_POSIX) && defined(LIBODB_MYSQL_THR_KEY_VISIBLE) # include #endif #include // abort +#include +#include + #include #include #include -#include -#include - // This key is in the mysql client library. We use it to resolve the // following problem: Some pthread implementations zero-out slots that // don't have destructors during thread termination. As a result, when @@ -32,7 +33,7 @@ // 1. MySQL doesn't use the destructor itself. // 2. Nobody else tried to call mysql_thread_end() before us. // -#ifdef ODB_THREADS_POSIX +#if defined(ODB_THREADS_POSIX) && defined(LIBODB_MYSQL_THR_KEY_VISIBLE) extern pthread_key_t THR_KEY_mysys; #endif @@ -64,7 +65,7 @@ namespace odb init_ = true; -#ifdef ODB_THREADS_POSIX +#if defined(ODB_THREADS_POSIX) && defined(LIBODB_MYSQL_THR_KEY_VISIBLE) value_ = pthread_getspecific (THR_KEY_mysys); #endif } @@ -74,7 +75,7 @@ namespace odb { if (init_) { -#ifdef ODB_THREADS_POSIX +#if defined(ODB_THREADS_POSIX) && defined(LIBODB_MYSQL_THR_KEY_VISIBLE) if (pthread_getspecific (THR_KEY_mysys) == 0) pthread_setspecific (THR_KEY_mysys, value_); #endif @@ -84,7 +85,7 @@ namespace odb private: bool init_; -#ifdef ODB_THREADS_POSIX +#if defined(ODB_THREADS_POSIX) && defined(LIBODB_MYSQL_THR_KEY_VISIBLE) void* value_; #endif #endif // ODB_THREADS_NONE @@ -96,21 +97,31 @@ namespace odb { mysql_process_init () { - if (mysql_library_init (0 ,0, 0)) - abort (); - + // Force allocation of our thread-specific key before THR_KEY_mysys + // in MySQL. This will (hopefully) get us the desired order of TLS + // destructor calls (i.e., our destructor before zeroing-out the + // THR_KEY_mysys value). This is pretty much the only way (except + // maybe guessing the THR_KEY_mysys value) to get clean thread + // termination if THR_KEY_mysys symbol is hidden, as is the case + // in the Fedora build of libmysqlclient. See also the comment + // at the beginning of this file. + // main_thread_init_ = true; tls_get (mysql_thread_init_); main_thread_init_ = false; + + if (mysql_library_init (0 ,0, 0)) + abort (); } ~mysql_process_init () { + mysql_library_end (); + // Finalize the main thread now in case TLS destruction // doesn't happen for the main thread. // tls_free (mysql_thread_init_); - mysql_library_end (); } }; diff --git a/odb/mysql/details/config.h.in b/odb/mysql/details/config.h.in index 8231ed8..6f70c3e 100644 --- a/odb/mysql/details/config.h.in +++ b/odb/mysql/details/config.h.in @@ -13,4 +13,6 @@ #undef LIBODB_MYSQL_INCLUDE_SHORT #undef LIBODB_MYSQL_INCLUDE_LONG +#undef LIBODB_MYSQL_THR_KEY_VISIBLE + #endif /* ODB_MYSQL_DETAILS_CONFIG_H */ diff --git a/odb/mysql/makefile b/odb/mysql/makefile index 1b14f60..4ae255f 100644 --- a/odb/mysql/makefile +++ b/odb/mysql/makefile @@ -80,6 +80,7 @@ $(out_base)/details/config.h: | $(out_base)/details/. @echo '#define ODB_MYSQL_DETAILS_CONFIG_H' >>$@ @echo '' >>$@ @echo '#define LIBODB_MYSQL_INCLUDE_LONG 1' >>$@ + @echo '#define LIBODB_MYSQL_THR_KEY_VISIBLE 1' >>$@ @echo '' >>$@ @echo '#endif /* ODB_MYSQL_DETAILS_CONFIG_H */' >>$@ -- cgit v1.1