]> git.sur5r.net Git - openldap/commitdiff
Allow mdb_cursor_close() after readonly txn ends.
authorHallvard Furuseth <hallvard@openldap.org>
Sat, 4 May 2013 10:34:02 +0000 (12:34 +0200)
committerHallvard Furuseth <hallvard@openldap.org>
Sat, 4 May 2013 10:34:02 +0000 (12:34 +0200)
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

index 8254a886353747f5d28cdcb1d90cf7f68220d498..0df2142dc2c8cde0380013ad5573c8e33efa0f67 100644 (file)
@@ -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)