From afe488d8a9c4dcdf09d1b33014b616a27e8e707f Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Thu, 18 Apr 2013 04:16:07 +0200 Subject: [PATCH] Catch MDB txn reuse/sync errors. --- libraries/liblmdb/lmdb.h | 4 +++- libraries/liblmdb/mdb.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/liblmdb/lmdb.h b/libraries/liblmdb/lmdb.h index 5cf8bd7..b2525ed 100644 --- a/libraries/liblmdb/lmdb.h +++ b/libraries/liblmdb/lmdb.h @@ -370,7 +370,9 @@ typedef enum MDB_cursor_op { #define MDB_MAP_RESIZED (-30785) /** Database flags changed or would change */ #define MDB_INCOMPATIBLE (-30784) -#define MDB_LAST_ERRCODE MDB_INCOMPATIBLE + /** Invalid reuse of reader locktable slot */ +#define MDB_BAD_RSLOT (-30783) +#define MDB_LAST_ERRCODE MDB_BAD_RSLOT /** @} */ /** @brief Statistics for a database in the environment */ diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 72ffa7e..471dcd0 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1083,6 +1083,7 @@ static char *const mdb_errstr[] = { "MDB_PAGE_FULL: Internal error - page has no more space", "MDB_MAP_RESIZED: Database contents grew beyond environment mapsize", "MDB_INCOMPATIBLE: Database flags changed or would change", + "MDB_BAD_RSLOT: Invalid reuse of reader locktable slot", }; char * @@ -1792,7 +1793,10 @@ mdb_txn_renew0(MDB_txn *txn) txn->mt_u.reader = NULL; } else { MDB_reader *r = pthread_getspecific(env->me_txkey); - if (!r) { + if (r) { + if (r->mr_pid != env->me_pid || r->mr_txnid != (txnid_t)-1) + return MDB_BAD_RSLOT; + } else { pid_t pid = env->me_pid; pthread_t tid = pthread_self(); @@ -1863,7 +1867,7 @@ mdb_txn_renew(MDB_txn *txn) { int rc; - if (! (txn && (txn->mt_flags & MDB_TXN_RDONLY))) + if (!txn || txn->mt_numdbs || !(txn->mt_flags & MDB_TXN_RDONLY)) return EINVAL; if (txn->mt_env->me_flags & MDB_FATAL_ERROR) { @@ -2066,6 +2070,10 @@ mdb_txn_reset(MDB_txn *txn) txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', (void *) txn, (void *)txn->mt_env, txn->mt_dbs[MAIN_DBI].md_root); + /* This call is only valid for read-only txns */ + if (!(txn->mt_flags & MDB_TXN_RDONLY)) + return; + mdb_txn_reset0(txn); }