aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-06-15 11:16:44 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-06-15 11:16:44 +0200
commitaf2808859e7a98666785752b8069c473dda94a1f (patch)
tree123979c9700e588ad0f3007c19c096646dd73704
parent5bfec1c98e05b86b719edb37ce1be8778f91d6ec (diff)
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.
-rw-r--r--configure.ac4
-rw-r--r--m4/libmysqlclient.m422
-rw-r--r--odb/mysql/connection-factory.cxx37
-rw-r--r--odb/mysql/details/config.h.in2
-rw-r--r--odb/mysql/makefile1
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 <pthread.h>
+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/details/config.hxx> // ODB_THREADS_*
+#include <odb/details/config.hxx> // ODB_THREADS_*
+#include <odb/mysql/details/config.hxx> // LIBODB_MYSQL_THR_KEY_VISIBLE
-#ifdef ODB_THREADS_POSIX
+#if defined(ODB_THREADS_POSIX) && defined(LIBODB_MYSQL_THR_KEY_VISIBLE)
# include <pthread.h>
#endif
#include <cstdlib> // abort
+#include <odb/details/tls.hxx>
+#include <odb/details/lock.hxx>
+
#include <odb/mysql/mysql.hxx>
#include <odb/mysql/connection-factory.hxx>
#include <odb/mysql/exceptions.hxx>
-#include <odb/details/tls.hxx>
-#include <odb/details/lock.hxx>
-
// 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 */' >>$@