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. Fix: Fix and/or workaround unknown (other than to execute from a created thread). 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 --------------------
Hi, On FreeBSD-CURRENT, if I do: gcc pthread_atforkbug.c -lkse && ./a.out This is the output: parent pid (48871) Child exiting: (48872) child (48872) returned If I do: gcc pthread_atforkbug.c -lkse && ./a.out parent pid (48877) af_prepare: pid (48877) af_parent: pid (48877) af_child: pid (48878) Child exiting: (48878) child (48878) returned On FreeBSD 6.2, -pthread is mapped to -lkse, while on CURRENT, it is mapped to -lthr. Can you try your test again with -lthr on FreeBSD 6.2? This looks like a libkse bug. -- Craig Rodrigues rodrigc@crodrigues.org
> Hi, > > On FreeBSD-CURRENT, if I do: > > gcc pthread_atforkbug.c -lkse && ./a.out > > This is the output: > > parent pid (48871) > Child exiting: (48872) > child (48872) returned > > If I do: > > gcc pthread_atforkbug.c -lkse && ./a.out > > parent pid (48877) > af_prepare: pid (48877) > af_parent: pid (48877) > af_child: pid (48878) > Child exiting: (48878) > child (48878) returned > > > On FreeBSD 6.2, -pthread is mapped to -lkse, while on CURRENT, it is mapped > to -lthr. Can you try your test again with -lthr on FreeBSD 6.2? > This looks like a libkse bug. > > -- > Craig Rodrigues > rodrigc@crodrigues.org Yes, I can verify that using: -pthread => erroneous behavior -lthr => expected behavior on my installation of 6.2. - dmw