On Mon, Jun 28, 2010 at 11:30:49AM -0400, Eric Smith wrote:
> From the docs:
> > Under Unix, you should not carry an open SQLite database across a
> > fork() system call into the child process. Problems will result if you
> > do.
> What if I fork a process that promises not to use the handle, and
> furthermore the child process certainly dies before the parent does?

Libraries could well (and many do) make use of pthread_atfork(3C) to
render "handles" unusable in a child process.  If an API is described as
caller "should not" or "must not" follow fork(2) then you need to be
prepared for it to use pthread_atfork(3C) as described, either now or in
the future.

> Will this still cause problems?
> What if I add an additional assumption that the parent process is the
> only process that ever accesses the database?

I strongly recommend that you always make the child side of fork(2)
either exit(2) or exec(2) immediately.  Self re-exec()ing is fine, if
you can pass in whatever state you need preserved on the command-line
and/or pipe and/or temp file.  If you're going to fork(2) and neither
exit nor exec then you should be careful to do whatever cleanup the
various libraries demand, and stick to whatever fork-safety protocol
they insist on, if any.  Not all fork-unsafe libraries will give you a
way to re-initialize them on the child-side of fork(2); the only
fool-proof way forward is to exec(2) in the child of fork(2).

With respect to SQLite3, there are two sets of fork-safety issues: file
descriptor offsets (use USE_PREAD to avoid this issue), and POSIX file
byte range locks.  There may be other fork-safety issues too that don't
leap to my mind at this time.  Basically, fork(2) must be handled with
extreme care.

The easiest thing for library developers to do is to declare their
libraries to be fork-unsafe and make the matter a problem for their
callers, which in a sufficiently layered system means many libraries
become inherently fork-unsafe, which leads one to conclude even more
strongly that one must always exec(2) or exit(2) the child of fork(2).
What you really need from libraries is a way to recover whatever state
you'll want to re-establish after exec()ing in the child.  SQLite3 has
no such state (what state it has the caller already knows how to
re-create).  (Think of crypto APIs, where the state of a cipher might
not be feasible to reproduce with ease; there you need the library to
give you a way to export the cipher's state.)

sqlite-users mailing list

Reply via email to