threads/115211: pthread_atfork misbehaves in initial thread

Douglas Wells sysmaint at contek.com
Sun Aug 5 02:40:02 PDT 2007


>Number:         115211
>Category:       threads
>Synopsis:       pthread_atfork misbehaves in initial thread
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-threads
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 05 09:40:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Douglas Wells
>Release:        FreeBSD 6.2-RELEASE-p1 i386
>Organization:
>Environment:
System: FreeBSD flame.contek.com 6.2-RELEASE-p1 FreeBSD 6.2-RELEASE-p1 #0: Sun Feb 11 18:14:07 EST 2007 root at flame.contek.com:/other5/src.6.2/sys/i386/compile/FLAME.6.2 i386


	Above system is patched up to SA-07:07.bind.
	Using default compiler: gcc version 3.4.6 [FreeBSD] 20060305.
>Description:
	If pthread_atfork is invoked in the original thread of a process,
	it does *not* invoke the various handlers.  If the same test is
	invoked from a created thread, it invokes the various handlers
	as expected.
	I don't see any exception in the POSIX standard that supports this,
	and the test program runs as expected on a recent OS/X.

>How-To-Repeat:
	Use the included test program.

	If compiled and run as: "gcc -pthread atforkbug.c && ./a.out",
	example (erroneous) output is:
		parent pid (11263)
		Child exiting: (11264)
		child (11264) returned

	If compiled and run as: "gcc -DUSE_NEW_THREAD -pthread atforkbug.c && ./a.out",
	the program behaves as I expect:
		parent pid (11270)
		af_prepare:  pid (11270)
		 af_parent:  pid (11270)
		  af_child:  pid (11271)
		Child exiting: (11271)
		child (11271) returned

	------------------------- test program ----------------------

	#include <stdlib.h>
	#include <stdio.h>
	#include <stdbool.h>
	#include <errno.h>
	#include <assert.h>

	#include <unistd.h>
	#include <pthread.h>
	#include <sys/types.h>
	#include <sys/wait.h>

	#if	defined (USE_NEW_THREAD)
	bool	run_in_separate_thread = true;
	#else
	bool	run_in_separate_thread = false;
	#endif

	void
	af_prepare (void)
	{
		fprintf (stderr, "af_prepare:  pid (%ld)\n", (long) getpid ());
	}

	void
	af_parent (void)
	{
		fprintf (stderr, " af_parent:  pid (%ld)\n", (long) getpid ());
	}

	void
	af_child (void)
	{
		fprintf (stderr, "  af_child:  pid (%ld)\n", (long) getpid ());
	}

	void *
	run_test (void *arg)
	{
		pid_t	child, xpid;
		int	err;

		(void) arg;

		err = pthread_atfork (af_prepare, af_parent, af_child);
		assert (err == 0);

		switch ((int) (child = fork ()))
		{
		case -1:
			assert (! "bad fork");
		case 0:			/* child here */
			sleep (1);
			fprintf (stderr, "Child exiting: (%ld)\n", (long) getpid ());
			exit (EXIT_SUCCESS);
		default:
			xpid = waitpid (child, NULL, 0);
			assert (xpid == child);
			fprintf (stdout, "child (%ld) returned\n", (long) child);
		}

		return NULL;
	}

	int
	main (void)
	{
		fprintf (stdout, "parent pid (%ld)\n", (long) getpid ());

		if (run_in_separate_thread)
		{
			pthread_t	tid;
			int		err;

			err = pthread_create (&tid, NULL, run_test, NULL);
			assert (err == 0);
			err = pthread_join (tid, NULL);
			assert (err == 0);
		}
		else	run_test (NULL);

		return EXIT_SUCCESS;
	}

	----------------------- end test program --------------------

>Fix:

	Fix and/or workaround unknown (other than to execute from
	a created thread).
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-threads mailing list