From 385889b0bee53b355f64d1749ba1e7788f7c66cb Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Sat, 4 May 2013 12:34:02 +0200 Subject: [PATCH] Allow mdb_cursor_close() after readonly txn ends. Catch mdb_cursor_renew(write txn's cursor). Add flag C_UNTRACK, so mdb_cursor_close need not peek inside a possibly-freed readonly txn. --- libraries/liblmdb/mdb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 8254a88..0df2142 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -900,6 +900,7 @@ struct MDB_cursor { #define C_SHADOW 0x08 /**< Cursor is a dup from a parent txn */ #define C_ALLOCD 0x10 /**< Cursor was malloc'd */ #define C_SPLITTING 0x20 /**< Cursor is in page_split */ +#define C_UNTRACK 0x40 /**< Un-track cursor when closing */ /** @} */ unsigned int mc_flags; /**< @ref mdb_cursor */ MDB_page *mc_pg[CURSOR_STACK]; /**< stack of pushed pages */ @@ -5858,6 +5859,7 @@ mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret) if (txn->mt_cursors) { mc->mc_next = txn->mt_cursors[dbi]; txn->mt_cursors[dbi] = mc; + mc->mc_flags |= C_UNTRACK; } mc->mc_flags |= C_ALLOCD; } else { @@ -5877,7 +5879,7 @@ mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc) if (txn == NULL || mc == NULL || mc->mc_dbi >= txn->mt_numdbs) return EINVAL; - if (txn->mt_cursors) + if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors) return EINVAL; flags = mc->mc_flags; @@ -5917,7 +5919,7 @@ mdb_cursor_close(MDB_cursor *mc) { if (mc != NULL) { /* remove from txn, if tracked */ - if (mc->mc_txn->mt_cursors) { + if ((mc->mc_flags & C_UNTRACK) && mc->mc_txn->mt_cursors) { MDB_cursor **prev = &mc->mc_txn->mt_cursors[mc->mc_dbi]; while (*prev && *prev != mc) prev = &(*prev)->mc_next; if (*prev == mc)