Date: Thu, 3 Aug 2006 14:34:04 -0400 (EDT) From: Daniel Eischen <deischen@freebsd.org> To: Poul-Henning Kamp <phk@phk.freebsd.dk> Cc: FreeBSD-gnats-submit@freebsd.org, freebsd-threads@freebsd.org Subject: Re: threads/101323: fork(2) in threaded programs broken. Message-ID: <Pine.GSO.4.64.0608031417260.13543@sea.ntplx.net> In-Reply-To: <49426.1154628688@critter.freebsd.dk> References: <49426.1154628688@critter.freebsd.dk>
next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 3 Aug 2006, Poul-Henning Kamp wrote: > In message <Pine.GSO.4.64.0608031348490.13543@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.64.0608031417260.13543>