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

Poul-Henning Kamp phk at phk.freebsd.dk
Thu Aug 3 18:12:21 UTC 2006


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.

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

Poul-Henning


Index: thr_fork.c
===================================================================
RCS file: /home/ncvs/src/lib/libpthread/thread/thr_fork.c,v
retrieving revision 1.37
diff -u -r1.37 thr_fork.c
--- thr_fork.c	13 Mar 2006 00:59:51 -0000	1.37
+++ thr_fork.c	3 Aug 2006 18:09:44 -0000
@@ -93,10 +93,10 @@
 	}
 
 	/* Fork a new process: */
-	if (_kse_isthreaded() != 0) {
-		_malloc_prefork();
-	}
-	if ((ret = __sys_fork()) == 0) {
+	_malloc_prefork();
+	ret = __sys_fork();
+	_malloc_postfork();
+	if (ret == 0) {
 		/* Child process */
 		errsave = errno; 
 
@@ -110,9 +110,6 @@
 		}
 		_thr_mutex_reinit(&_thr_atfork_mutex);
 	} else {
-		if (_kse_isthreaded() != 0) {
-			_malloc_postfork();
-		}
 		errsave = errno; 
 		if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
 			__sys_sigprocmask(SIG_SETMASK, &oldset, NULL);

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk at FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe    
Never attribute to malice what can adequately be explained by incompetence.


More information about the freebsd-threads mailing list