threads/101323: fork(2) in threaded programs broken.

Daniel Eischen deischen at freebsd.org
Thu Aug 3 18:40:18 UTC 2006


The following reply was made to PR threads/101323; it has been noted by GNATS.

From: Daniel Eischen <deischen at freebsd.org>
To: Poul-Henning Kamp <phk at phk.freebsd.dk>
Cc: FreeBSD-gnats-submit at freebsd.org, freebsd-threads at freebsd.org
Subject: Re: threads/101323: fork(2) in threaded programs broken.
Date: Thu, 3 Aug 2006 14:34:04 -0400 (EDT)

 On Thu, 3 Aug 2006, Poul-Henning Kamp wrote:
 
 > In message <Pine.GSO.4.64.0608031348490.13543 at sea.ntplx.net>, Daniel Eischen writes:
 >> On Thu, 3 Aug 2006, Poul-Henning Kamp wrote:
 >>
 >>> 	Forking a threaded process and starting a thread in the
 >>> 	child process does not work.
 >>>
 >>> 	Tested on -current and releng_6 and both fails with more or
 >>> 	less the same error message:
 >>>
 >>> 	Fatal error 'mutex is on list' at line 540 in file
 >>> 	    /usr/src/lib/libpthread/thread/thr_mutex.c (errno = 0)
 >>
 >> fork()ing from a threaded process and making calls to functions
 >> other than those defined as async-signal-safe is not allowed
 >> by POSIX.  libpthread intentionally doesn't support this.
 >
 > As you may probably be aware, I don't hold great respect for
 > POSIX when it comes to writing useful APIs :-)
 >
 > First of all, there is a difference between POSIX explicitly
 > disallowing something and POSIX not guaranteeing that something
 > works.
 >
 > I belive we are in the second range here.
 
 You should read section 2.4.3 of "Signal Concepts" in
 the POSIX spec.
 
 > Both Solaris and Linux support the usage which FreeBSD fails and
 > as far as I can tell from our source-code, we also go a long way
 > to make it work, just not long enough.
 >
 > As far as I can tell, all that's need to make it work correctly is
 > the attached patch (which I've sent to Jason Evans since it's malloc related.)
 
 No, that's not nearly enough.  This has been discussed in
 -threads before.
 
 Forking from a multi-threaded program is just like an
 asynchronous signal in an unthreaded program.  You have
 no idea what state any of the libraries or application data
 is in.  Other threads may have taken either library or
 application locks and left things in an inconsistent
 state.  The only sure way to safely fork() from a threaded
 process is to suspend threads while assuring they are
 not in critical regions, then fork() and reinitialize
 any necessary library global data in the child, and
 resume the suspended threads in the parent after the
 fork().
 
 It may seem simple to #define NOTYET in
 src/lib/libpthread/thread/thr_kern.c but that isn't
 going to guarantee that libc or other library data is
 left in a consistent state and that their locks are
 reinitialized.
 
 -- 
 DE


More information about the freebsd-threads mailing list