https://bugs.openldap.org/show_bug.cgi?id=10395
--- Comment #23 from Howard Chu hyc@openldap.org --- + /* mark parent txn has no longer having children if this is the last nested txn */ + int last_child = 0; + if (F_ISSET(flags, MDB_RDONLY)) { + pthread_mutex_lock(&txn->mt_parent->mt_child_mutex); + txn->mt_parent->mt_rdonly_child_count--; + last_child = (txn->mt_parent->mt_rdonly_child_count == 0); + pthread_mutex_unlock(&txn->mt_parent->mt_child_mutex); + } + if (!F_ISSET(flags, MDB_RDONLY) || last_child) { + txn->mt_parent->mt_child = NULL; + txn->mt_parent->mt_flags &= ~MDB_TXN_HAS_CHILD; + }
This is racy. A new child rtxn could come along after you set last_child but before you test it.
That whole sequence of `if (F_ISSET(flags, MDB_RDONLY))` tests needs to be consolidated.