Full_Name: Hallvard B Furuseth Version: LMDB_0.9.18 OS: Linux URL: Submission from: (NULL) (81.191.45.31) Submitted by: hallvard
This is from openldap-tecnical thread "Using LMDB safely with fork() and exec()" by Lorenz Bauer: http://www.openldap.org/lists/openldap-technical/201608/msg00062.html
====
The doc is too restrictive, it implicitly suggests an LMDB process can't fork another LDMB process (since the old LMDB would still be open). We should document the use of FD_CLOEXEC etc.
====
This breaks LMDB: if (fork() == 0) pthread_exit(NULL); because the child's me_txkey destructor releases the reader slot. This can happen if a single-threaded LMDB process forks a multi- threaded child, which is one way to deal with threads vs. fork().
Simplest fix: Check if (reader->mr_pid == getpid()) in reader_dest().
We could instead use pthread_atfork(), but there is not way to remove an atfork handler. It seems to be implementation-dependent what happens with an atfork handler if liblmdb is dynamically unloaded.
====
LMDB leaks file descriptors to a fork() child, since the user may not call mdb_env_close() and there is no way to get at some of the descriptors.
Partial fix: Set FD_CLOEXEC for me_mfd and the mdb_env_copy() FD.
Should I code up an mdb_env_child_cleanup() function which may be called in the child if it does not fork()? That makes sense either if the parent is single-threaded and forks a more complex child, or if the child is fairly simple.
====
Branch "mdb/fopen2" in my repo will soon include suggested fixes, except mdb_env_child_cleanup(). (Fixed version of older "mdb/fopen")