From fb89d7b078d2c7d0c01913b0bd5c5691684ae62072d0e08ded543a3bd363f95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= Date: Mon, 28 Jul 2014 15:59:55 +0000 Subject: [PATCH] - Prevent deadlock when process holding the db lock dies 0001-Patch-for-LMDB-to-use-robust-mutexes.patch - command line tools for debugging 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch - Switch to cmake, fix dynamic lib build and versioning. OBS-URL: https://build.opensuse.org/package/show/systemsmanagement/lmdb?expand=0&rev=8 --- ...Patch-for-LMDB-to-use-robust-mutexes.patch | 93 +++++ ...-and-CFEngine-modifications-for-LMDB.patch | 349 ++++++++++++++++++ lmdb.changes | 11 +- lmdb.spec | 9 +- 4 files changed, 460 insertions(+), 2 deletions(-) create mode 100644 0001-Patch-for-LMDB-to-use-robust-mutexes.patch create mode 100644 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch diff --git a/0001-Patch-for-LMDB-to-use-robust-mutexes.patch b/0001-Patch-for-LMDB-to-use-robust-mutexes.patch new file mode 100644 index 0000000..e7b03f2 --- /dev/null +++ b/0001-Patch-for-LMDB-to-use-robust-mutexes.patch @@ -0,0 +1,93 @@ +diff -wruN -x '*~' -x '*.o' -x '*.a' -x '*.so' -x '*.so.[0-9]' -x autom4te.cache -x .deps -x .libs ../orig-liblmdb/configure.ac ./configure.ac +--- ../orig-liblmdb/configure.ac 2014-07-28 17:44:41.873398363 +0200 ++++ ./configure.ac 2014-07-28 17:47:06.143497590 +0200 +@@ -9,5 +9,12 @@ + m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + LT_INIT + AC_CHECK_HEADERS([sys/file.h]) ++AC_CHECK_LIB([pthread], [pthread_mutex_lock]) ++AC_CHECK_LIB([pthreadGC2], [pthread_mutex_lock]) ++AS_IF([test "$ac_cv_lib_pthread" = "no" && test "$ac_cv_lib_pthreadGC2" = "no"], ++[ ++ AC_MSG_ERROR([Could not find pthreads library]) ++]) ++AC_CHECK_FUNCS([pthread_mutexattr_settype pthread_mutexattr_setrobust]) + AC_CONFIG_FILES([Makefile]) + AC_OUTPUT +diff -wruN -x '*~' -x '*.o' -x '*.a' -x '*.so' -x '*.so.[0-9]' -x autom4te.cache -x .deps -x .libs ../orig-liblmdb/mdb.c ./mdb.c +--- ../orig-liblmdb/mdb.c 2014-01-31 09:23:13.341427766 +0100 ++++ ./mdb.c 2014-07-28 17:44:55.145959267 +0200 +@@ -169,6 +169,7 @@ + #ifdef _WIN32 + #define MDB_USE_HASH 1 + #define MDB_PIDLOCK 0 ++#define EOWNERDEAD 130 + #define pthread_t DWORD + #define pthread_mutex_t HANDLE + #define pthread_key_t DWORD +@@ -179,7 +180,7 @@ + #define pthread_getspecific(x) TlsGetValue(x) + #define pthread_setspecific(x,y) (TlsSetValue(x,y) ? 0 : ErrCode()) + #define pthread_mutex_unlock(x) ReleaseMutex(x) +-#define pthread_mutex_lock(x) WaitForSingleObject(x, INFINITE) ++#define pthread_mutex_lock(x) (WaitForSingleObject(x, INFINITE) == WAIT_ABANDONED ? EOWNERDEAD : 0) // masks FAIL and TIMEOUT error, but acceptable + #define LOCK_MUTEX_R(env) pthread_mutex_lock((env)->me_rmutex) + #define UNLOCK_MUTEX_R(env) pthread_mutex_unlock((env)->me_rmutex) + #define LOCK_MUTEX_W(env) pthread_mutex_lock((env)->me_wmutex) +@@ -2275,7 +2276,20 @@ + env->me_flags |= MDB_LIVE_READER; + } + +- LOCK_MUTEX_R(env); ++ rc = LOCK_MUTEX_R(env); ++ switch (rc) ++ { ++ case 0: ++ break; ++#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST ++ case EOWNERDEAD: ++ // we cannot recover the state, so mark mutex as unusable ++ UNLOCK_MUTEX_R(env); ++ // FALLTHROUGH ++#endif ++ default: ++ return MDB_PANIC; ++ } + nr = ti->mti_numreaders; + for (i=0; imti_readers[i].mr_pid == 0) +@@ -2305,7 +2319,20 @@ + } + } else { + if (ti) { +- LOCK_MUTEX_W(env); ++ rc = LOCK_MUTEX_W(env); ++ switch (rc) ++ { ++ case 0: ++ break; ++#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST ++ case EOWNERDEAD: ++ // we cannot recover the state, so mark mutex as unusable ++ UNLOCK_MUTEX_W(env); ++ // FALLTHROUGH ++#endif ++ default: ++ return MDB_PANIC; ++ } + + txn->mt_txnid = ti->mti_txnid; + meta = env->me_metas[txn->mt_txnid & 1]; +@@ -4014,6 +4041,12 @@ + pthread_mutexattr_t mattr; + + if ((rc = pthread_mutexattr_init(&mattr)) ++#ifdef HAVE_PTHREAD_MUTEXATTR_SETTYPE ++ || (rc = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK)) ++#endif ++#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST ++ || (rc = pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST)) ++#endif + || (rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) + || (rc = pthread_mutex_init(&env->me_txns->mti_mutex, &mattr)) + || (rc = pthread_mutex_init(&env->me_txns->mti_wmutex, &mattr))) diff --git a/0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch b/0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch new file mode 100644 index 0000000..4616c3e --- /dev/null +++ b/0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch @@ -0,0 +1,349 @@ +diff -wruN -x '*~' -x '*.o' -x '*.a' -x '*.so' -x '*.so.[0-9]' -x autom4te.cache -x .deps -x .libs ../orig-liblmdb/lmdump.c ./lmdump.c +--- ../orig-liblmdb/lmdump.c 1970-01-01 01:00:00.000000000 +0100 ++++ ./lmdump.c 2014-07-28 17:50:23.263838569 +0200 +@@ -0,0 +1,128 @@ ++/* lmdump.c - Lmdb database dumper ++ Has three modes : ++ -a : print keys in ascii form ++ -A : print keys and values in ascii form ++ -x : print keys and values in hexadecimal form ++ -d : print only the size of keys and values ++ */ ++ ++#define _XOPEN_SOURCE 500 /* srandom(), random() */ ++#include ++#include ++#include ++#include ++#include "lmdb.h" ++ ++static void print_hex(char *s, int len) ++{ ++ int i = 0; ++ for (i=0; i ++#include ++#include "lmdb.h" ++ ++static int report_error(int rc) ++{ ++ printf("err(%d): %s\n", rc, mdb_strerror(rc)); ++ return rc; ++} ++ ++int openconn(const char *dbfile, MDB_env **env, long int maxreaders) ++{ ++/*init*/ ++ int rc; ++ rc = mdb_env_create(env); ++ if(rc) return report_error(rc); ++ ++ rc = mdb_env_open(*env, dbfile, MDB_NOSUBDIR, 0644); ++ if(rc) return report_error(rc); ++ return 0; ++} ++ ++int gettxn(MDB_env *env, MDB_txn **txn, MDB_dbi *dbi) ++{ ++ int rc; ++/*setup txn*/ ++ rc = mdb_txn_begin(env, NULL, 0, txn); ++ if(rc) return report_error(rc); ++ rc = mdb_open(*txn, NULL, 0, dbi); ++ if(rc) return report_error(rc); ++ return 0; ++} ++ ++int committxn(MDB_txn *txn) ++{ ++/*commit*/ ++ int rc; ++ rc = mdb_txn_commit(txn); ++ return 0; ++} ++ ++int aborttxn(MDB_txn *txn) ++{ ++/*abort*/ ++ int rc; ++ mdb_txn_abort(txn); ++ return 0; ++} ++ ++int closeall(MDB_env *env, MDB_txn *txn, MDB_dbi dbi) ++{ ++/*end*/ ++ mdb_close(env, dbi); ++ mdb_env_close(env); ++ return 0; ++} ++ ++int do_put(char *dbfile, char *mykey, char *myval) ++{ ++ MDB_env *env; ++ openconn(dbfile, &env, 0); ++ ++ MDB_txn *txn; ++ MDB_dbi dbi; ++ gettxn(env, &txn, &dbi); ++ ++ int rc; ++ MDB_val key, data; ++ key.mv_data = mykey; ++ data.mv_data = myval; ++ key.mv_size = strlen(mykey) + 1; ++ data.mv_size = strlen(myval) + 1; ++ ++ rc = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); ++ if (rc == MDB_SUCCESS) ++ { ++ rc = mdb_txn_commit(txn); ++ } ++ else ++ { ++ mdb_txn_abort(txn); ++ } ++ ++ mdb_env_close(env); ++ return rc; ++} ++ ++int do_del(char *dbfile, char *mykey) ++{ ++ MDB_env *env; ++ openconn(dbfile, &env, 0); ++ ++ MDB_txn *txn; ++ MDB_dbi dbi; ++ gettxn(env, &txn, &dbi); ++ ++ int rc; ++ MDB_val key; ++ key.mv_data = mykey; ++ key.mv_size = strlen(mykey) + 1; ++ ++ rc = mdb_del(txn, dbi, &key, NULL); ++ if (rc == MDB_SUCCESS) ++ { ++ rc = mdb_txn_commit(txn); ++ } ++ else ++ { ++ mdb_txn_abort(txn); ++ } ++ ++ mdb_env_close(env); ++ return rc; ++} ++ ++int do_init(char *dbfile, unsigned long maxr) ++{ ++ MDB_env *env; ++ openconn(dbfile, &env, maxr); ++ mdb_env_close(env); ++ return 0; ++} ++ ++int do_stat(char *dbfile) ++{ ++ int rc; ++ MDB_env *env; ++ openconn(dbfile, &env, 0); ++ ++ MDB_stat stat; ++ MDB_envinfo info; ++ ++ rc = mdb_env_stat(env, &stat); ++ rc = mdb_env_info(env, &info); ++ printf("me_maxreaders=%ld\n", info.me_maxreaders); ++ mdb_env_close(env); ++ return 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ if (argc < 3) ++ { ++ goto fail; ++ } ++ ++ if (!strcmp(argv[1], "put")) ++ { ++ if (argc == 5) ++ { ++ int rc = do_put(argv[2], argv[3], argv[4]); ++ return rc; ++ } ++ } ++ else if (!strcmp(argv[1], "del")) ++ { ++ if (argc == 4) ++ { ++ int rc = do_del(argv[2], argv[3]); ++ return rc; ++ } ++ } ++ else if (!strcmp(argv[1], "init")) ++ { ++ if (argc == 3) ++ { ++ int rc = do_init(argv[2], 0L); ++ return rc; ++ } ++ else if (argc == 5 && !strcmp(argv[3], "-m")) ++ { ++ int rc = do_init(argv[2], atol(argv[4])); ++ do_stat(argv[2]); ++ return rc; ++ } ++ } ++ else if (!strcmp(argv[1], "maxr")) ++ { ++ if (argc == 3) ++ { ++ int rc = do_stat(argv[2]); ++ return rc; ++ } ++ } ++ ++fail: ++ printf("Usage :\n"); ++ printf("Add a key and value to a DB file :\n"); ++ printf("\tlmmgr put dbfile key value\n"); ++ printf("Remove a key from a DB file :\n"); ++ printf("\tlmmgr del dbfile key\n"); ++ printf("Set a new maxreaders value of a DB file :\n"); ++ printf("\tlmmgr init dbfile [-m maxreaders]\n"); ++ printf("Give maxreaders value of a DB file :\n"); ++ printf("\tlmmgr maxr dbfile\n"); ++ ++ return 1; ++} +diff -wruN -x '*~' -x '*.o' -x '*.a' -x '*.so' -x '*.so.[0-9]' -x autom4te.cache -x .deps -x .libs ../orig-liblmdb/Makefile.am ./Makefile.am +--- ../orig-liblmdb/Makefile.am 2014-07-28 17:44:34.137071474 +0200 ++++ ./Makefile.am 2014-07-28 17:58:11.979702178 +0200 +@@ -4,7 +4,7 @@ + AM_CFLAGS = -W -Wall -Wno-unused-parameter -Wbad-function-cast -pthread + LDADD = liblmdb.la + +-bin_PROGRAMS = mdb_copy mdb_stat ++bin_PROGRAMS = mdb_copy mdb_stat lmdump lmmgr + check_PROGRAMS = mtest mtest2 mtest3 mtest4 mtest5 + man_MANS = mdb_copy.1 mdb_stat.1 + include_HEADERS = lmdb.h diff --git a/lmdb.changes b/lmdb.changes index 05dc1e3..95f1086 100644 --- a/lmdb.changes +++ b/lmdb.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Mon Jul 28 15:55:31 UTC 2014 - kkaempf@suse.com + +- Prevent deadlock when process holding the db lock dies + 0001-Patch-for-LMDB-to-use-robust-mutexes.patch + +- command line tools for debugging + 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch + ------------------------------------------------------------------- Fri May 16 20:00:29 UTC 2014 - jengelh@inai.de @@ -13,7 +22,7 @@ Fri May 16 20:00:29 UTC 2014 - jengelh@inai.de ------------------------------------------------------------------- Wed Feb 12 13:53:21 UTC 2014 - kkaempf@suse.com -- Switch to cmake build +- Switch to cmake, fix dynamic lib build and versioning. Drop liblmdb.patch Add VERSION.cmake and CMakeLists.txt diff --git a/lmdb.spec b/lmdb.spec index 5e2c0c2..0156100 100644 --- a/lmdb.spec +++ b/lmdb.spec @@ -28,6 +28,8 @@ Url: http://symas.com/mdb/ #Git-Clone: git://git.openldap.org/openldap mdb.master Source: %{name}-%{version}.tar.bz2 Patch1: automake.diff +Patch2: 0001-Patch-for-LMDB-to-use-robust-mutexes.patch +Patch3: 0002-Add-extra-tools-and-CFEngine-modifications-for-LMDB.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: autoconf BuildRequires: automake >= 1.10 @@ -76,7 +78,12 @@ the liblmdb library. %prep %setup -qn liblmdb -%patch -P 1 -p1 +# PATCH-FIX-OPENSUSE - autotools files, jengelh@inai.de +%patch1 -p1 +# PATCH-FIX-UPSTREAM - prevent deadlock when process holding db lock dies, kkaempf@suse.de +%patch2 -p1 +# PATCH-FIX-OPENSUSE - debugging tools (https://github.com/kacfengine/lmdb) +%patch3 -p1 %build mkdir -p m4