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