[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#8505) LMDB vs. fork()



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")