Full_Name: zgrim Version: 2.4.40 OS: Linux URL: ftp://ftp.openldap.org/incoming/ Submission from: (NULL) (79.115.186.237)
Hello, thank you for lmdb. I'm using lmdb via a Go wrapper and under some not-yet-clear circumstances, under high concurrency stress testing, I sometimes get "double free or corruption" SIGABRT related to mdb_dbis_update(). The setup is using the NOTLS and RDONLY flags on a 64bit 3.17.0 Arch Linux system. If I protect the free() inside mdb_dbis_update() (in mdb.c) with a mutex (code inline below), the symptom disappears. I'm sorry I can't provide a simple test case, but in my code, without the mutex, launching some tens of test clients simultaneously trigger the corruption fairly quick, i.e. a few minutes or even seconds.
I tried older releases of lmdb as well as the latest git tree, 9a8eb95674c7b500cfe5f44d03493ff76c9fc0c1 of mdb.master, the bahaviour is the same.
I also tried several approaches in the higher level code, like either txn reset and renew and a pool of txns or simplified the code to bare bones to just abort after each transaction and remake new txns, it does not matter, the corruption happens the same.
If the problem should lie in the higher level code, I'd welcome your insights on possible culprits, I'm very new to lmdb. Thanks.
against latest git mentioned above i applied something like,
@@ -2769,19 +2769,24 @@ MDB_dbi n = txn->mt_numdbs; MDB_env *env = txn->mt_env; unsigned char *tdbflags = txn->mt_dbflags; + int rc = 0, rx = 0;
for (i = n; --i >= 2;) { if (tdbflags[i] & DB_NEW) { if (keep) { env->me_dbflags[i] = txn->mt_dbs[i].md_flags | MDB_VALID; } else { - char *ptr = env->me_dbxs[i].md_name.mv_data; - if (ptr) { + if (env->me_dbxs[i].md_name.mv_data != NULL) { + mdb_mutex_t *wmutex = MDB_MUTEX(env, w); + rc = LOCK_MUTEX(rx, env, wmutex); + + free(env->me_dbxs[i].md_name.mv_data); env->me_dbxs[i].md_name.mv_data = NULL; env->me_dbxs[i].md_name.mv_size = 0; env->me_dbflags[i] = 0; env->me_dbiseqs[i]++; - free(ptr); + + if (!rc) UNLOCK_MUTEX(wmutex); } } }