From c0f3519d2e841dbaad086091f610cebc8178e7f6 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 28 May 2000 22:14:55 +0000 Subject: Update. * posix/Makefile (tests): Add tst-fork. --- linuxthreads/ChangeLog | 20 ++++++++ linuxthreads/Examples/ex8.c | 101 +++++++++++++++++++++++++++++++++++++++++ linuxthreads/Makefile | 3 +- linuxthreads/linuxthreads.texi | 14 ++++++ linuxthreads/ptfork.c | 20 ++++---- 5 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 linuxthreads/Examples/ex8.c (limited to 'linuxthreads') diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 4bb1a81d17..38cbe5879b 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,23 @@ +2000-05-28 Ulrich Drepper + + * Makefile (tests): Add ex8. + * Examples/ex8.c: New file. + +2000-05-12 Kaz Kylheku + + Bugfix: The pthread_atfork mechanism now takes care of its + own internal mutex at fork time. + + * ptfork.c (__fork): Revised so that the mutex is held across + the fork operation and while the handlers are called, and so that + the child resets the mutex. + Added calls to new functions __flockallfiles and __funlockallfiles. + + * linuxthreads.texi: Updated pthread_atfork documentation to make + it clear that fork and pthread_atfork can't be reentered from + atfork handlers, that pthread_atfork and fork are mutually atomic, + and that the handlers are inherited by the child process. + 2000-05-24 Ulrich Drepper * Makefile (libpthread-routines): Add pspinlock. diff --git a/linuxthreads/Examples/ex8.c b/linuxthreads/Examples/ex8.c new file mode 100644 index 0000000000..89ad8ae5d5 --- /dev/null +++ b/linuxthreads/Examples/ex8.c @@ -0,0 +1,101 @@ +/* Tests for fork in multi-threaded environment. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Ulrich Drepper , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include + +enum +{ + PREPARE_BIT = 1, + PARENT_BIT = 2, + CHILD_BIT = 4 +}; + +static int var; + +static void +prepare (void) +{ + var |= PREPARE_BIT; +} + +static void +parent (void) +{ + var |= PARENT_BIT; +} + +static void +child (void) +{ + var |= CHILD_BIT; +} + + +static void *thread (void *arg); + + +int +main (void) +{ + pthread_t th; + void *res; + + pthread_atfork (prepare, parent, child); + + if (pthread_create (&th, NULL, thread, NULL) != 0) + error (EXIT_FAILURE, 0, "cannot create thread"); + + pthread_join (th, &res); + + return (int) res; +} + + +static void * +thread (void *arg) +{ + int status; + pid_t pid; + + pid = fork (); + if (pid == 0) + { + /* We check whether the `prepare' and `child' function ran. */ + exit (var != (PREPARE_BIT | CHILD_BIT)); + } + else if (pid == (pid_t) -1) + error (EXIT_FAILURE, errno, "cannot fork"); + + if (waitpid (pid, &status, 0) != pid) + error (EXIT_FAILURE, errno, "wrong child"); + + if (WTERMSIG (status) != 0) + error (EXIT_FAILURE, 0, "Child terminated incorrectly"); + status = WEXITSTATUS (status); + + if (status == 0) + status = var != (PREPARE_BIT | PARENT_BIT); + + return (void *) status; +} diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile index 777fb2b408..afbe51c618 100644 --- a/linuxthreads/Makefile +++ b/linuxthreads/Makefile @@ -38,7 +38,7 @@ libpthread-routines := attr cancel condvar join manager mutex ptfork \ oldsemaphore events getcpuclockid pspinlock vpath %.c Examples -tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 +tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 include ../Rules @@ -67,3 +67,4 @@ $(objpfx)ex4: $(libpthread) $(objpfx)ex5: $(libpthread) $(objpfx)ex6: $(libpthread) $(objpfx)ex7: $(libpthread) +$(objpfx)ex8: $(libpthread) diff --git a/linuxthreads/linuxthreads.texi b/linuxthreads/linuxthreads.texi index 2b3647aed0..f50199e9fc 100644 --- a/linuxthreads/linuxthreads.texi +++ b/linuxthreads/linuxthreads.texi @@ -1314,6 +1314,20 @@ handlers are called in FIFO order (first added, first called). If there is insufficient memory available to register the handlers, @code{pthread_atfork} fails and returns @code{ENOMEM}. Otherwise it returns 0. + +The functions @code{fork} and @code{pthread_atfork} must not be regarded as +reentrant from the context of the handlers. That is to say, if a +@code{pthread_atfork} handler invoked from within @code{fork} calls +@code{pthread_atfork} or @code{fork}, the behavior is undefined. + +Registering a triplet of handlers is an atomic operation with respect to fork. +If new handlers are registered at about the same time as a fork occurs, either +all three handlers will be called, or none of them will be called. + +The handlers are inherited by the child process, and there is no +way to remove them, short of using @code{exec} to load a new +pocess image. + @end deftypefun To understand the purpose of @code{pthread_atfork}, recall that diff --git a/linuxthreads/ptfork.c b/linuxthreads/ptfork.c index cb6d46db8c..440d66c4a3 100644 --- a/linuxthreads/ptfork.c +++ b/linuxthreads/ptfork.c @@ -78,25 +78,29 @@ extern int __libc_fork(void); pid_t __fork(void) { pid_t pid; - struct handler_list * prepare, * child, * parent; pthread_mutex_lock(&pthread_atfork_lock); - prepare = pthread_atfork_prepare; - child = pthread_atfork_child; - parent = pthread_atfork_parent; - pthread_mutex_unlock(&pthread_atfork_lock); - pthread_call_handlers(prepare); + + pthread_call_handlers(pthread_atfork_prepare); __pthread_once_fork_prepare(); + pid = __libc_fork(); + if (pid == 0) { __pthread_reset_main_thread(); + __fresetlockfiles(); - pthread_call_handlers(child); __pthread_once_fork_child(); + pthread_call_handlers(pthread_atfork_child); + + pthread_mutex_init(&pthread_atfork_lock, NULL); } else { - pthread_call_handlers(parent); __pthread_once_fork_parent(); + pthread_call_handlers(pthread_atfork_parent); + + pthread_mutex_unlock(&pthread_atfork_lock); } + return pid; } -- cgit 1.4.1