Full_Name: Lorenz Bauer
Version: git c367c1f69685
OS: OS X
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (2a06:98c0:1000:1200:156f:df88:ee9a:7775)


The function mdb_env_copyfd2 with MDB_CP_COMPACT enabled can currently deadlock,
since a call to mdb_env_cthr_toggle is not checked.

The testcase at https://gist.github.com/lmb/17a528cdadde73fb231a2a1ed84714f7
reproduces this issue as follows:

- Use pthread_sigmask to ignore SIGPIPE
- Create new pipe
- Spawn thread with mdb_env_copyfd2 using MDB_CP_COMPACT
- Close read side of the pipe in main thread
- Join thread and check rc code

On LMDB master the testase e hangs instead of returning EPIPE.

The following patch fixes the deadlock, but since I'm not very familiar with the
codebase it's likely incorrect.

diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c
index 79a958b..97ff7c7 100644
--- a/libraries/liblmdb/mdb.c
+++ b/libraries/liblmdb/mdb.c
@@ -9988,11 +9988,15 @@ mdb_env_copyfd1(MDB_env *env, HANDLE fd)
        rc = mdb_env_cwalk(&my, &txn->mt_dbs[MAIN_DBI].md_root, 0);
        if (rc == MDB_SUCCESS && my.mc_wlen[my.mc_toggle])
                rc = mdb_env_cthr_toggle(&my, 1);
-       mdb_env_cthr_toggle(&my, -1);
+       rc = mdb_env_cthr_toggle(&my, -1);
+       if (rc)
+               goto done;
        pthread_mutex_lock(&my.mc_mutex);
        while(my.mc_new)
                pthread_cond_wait(&my.mc_cond, &my.mc_mutex);
        pthread_mutex_uocock(&my.mc_mutex);
+
+done:
        THREAD_FINISH(thr);
 
        mdb_txn_abort(txn);



Reply via email to