aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-09-13 16:58:12 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-09-13 16:58:12 +0200
commit82aad8dee49a0c645ada631cc8aeb0266ba3ecc5 (patch)
tree6390e926ea1e9251c351151e133e669c822692e7
parent6652eb7ffb6dafb877344845ca24e938a50e4bfb (diff)
Fix MySQL thread termination problem
-rw-r--r--odb/mysql/connection-factory.cxx39
1 files changed, 38 insertions, 1 deletions
diff --git a/odb/mysql/connection-factory.cxx b/odb/mysql/connection-factory.cxx
index 645d03a..aae5cb9 100644
--- a/odb/mysql/connection-factory.cxx
+++ b/odb/mysql/connection-factory.cxx
@@ -3,6 +3,12 @@
// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
+#include <odb/details/config.hxx> // ODB_THREADS_*
+
+#ifdef ODB_THREADS_POSIX
+# include <pthread.h>
+#endif
+
#include <cstdlib> // abort
#include <odb/mysql/mysql.hxx>
@@ -11,7 +17,25 @@
#include <odb/details/tls.hxx>
#include <odb/details/lock.hxx>
-#include <odb/details/config.hxx> // ODB_THREADS_NONE
+
+// 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
+// out destructor gets called and we call mysql_thread_end(), the thread-
+// specific slot used by MySQL may have been reset to 0 and as a result
+// MySQL thinks the data has been freed.
+//
+// To work around this problem we are going to cache the MySQL's slot
+// value and if, during destruction, we see that it is 0, we will restore
+// the original value before calling mysql_thread_end(). This will work
+// fine for as long as the following conditions are met:
+//
+// 1. MySQL don't use the destructor itself.
+// 2. Nobody else tried to call mysql_thread_end() before us.
+//
+#ifdef ODB_THREADS_POSIX
+extern pthread_key_t THR_KEY_mysys;
+#endif
using namespace std;
@@ -40,18 +64,31 @@ namespace odb
}
init_ = true;
+
+#ifdef ODB_THREADS_POSIX
+ value_ = pthread_getspecific (THR_KEY_mysys);
+#endif
}
}
~mysql_thread_init ()
{
if (init_)
+ {
+#ifdef ODB_THREADS_POSIX
+ if (pthread_getspecific (THR_KEY_mysys) == 0)
+ pthread_setspecific (THR_KEY_mysys, value_);
+#endif
mysql_thread_end ();
+ }
}
private:
bool init_;
+#ifdef ODB_THREADS_POSIX
+ void* value_;
#endif
+#endif // ODB_THREADS_NONE
};
static ODB_TLS_OBJECT (mysql_thread_init) mysql_thread_init_;