diff options
-rw-r--r-- | nptl/ChangeLog | 16 | ||||
-rw-r--r-- | nptl/Makefile | 28 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/fork.c | 4 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/register-atfork.c | 36 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/unregister-atfork.c | 20 | ||||
-rw-r--r-- | nptl/tst-atfork1.c | 15 | ||||
-rw-r--r-- | nptl/tst-atfork2.c | 159 | ||||
-rw-r--r-- | nptl/tst-atfork2mod.c | 58 |
8 files changed, 325 insertions, 11 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 182d66bef6..03b6acb987 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,21 @@ 2003-02-12 Ulrich Drepper <drepper@redhat.com> + * Makefile: Add rules to build and run tst-atfork2 test. + * tst-atfork2.c: New file. + * tst-atfork2mod.c: New file. + + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Free the memory allocated for the handlers + after removing them from the lists. + + * sysdeps/unix/sysv/linux/register-atfork.c: Define memeory + cleanup function. + + * tst-atfork1.c (do_test): Wait for the child we forked. + Report error in child. + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Fix comment. + * sysdeps/pthread/Makefile: Define CFLAGS-confstr.c. 2003-02-10 Ulrich Drepper <drepper@redhat.com> diff --git a/nptl/Makefile b/nptl/Makefile index 3397482ee1..aa4540d8be 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -160,6 +160,18 @@ LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst include ../Makeconfig ifeq ($(build-shared),yes) +tests += tst-atfork2 +endif + +modules-names = tst-atfork2mod +extra-objs += $(addsuffix .os,$(strip $(modules-names))) +test-extras += $(modules-names) +test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) + +$(test-modules): $(objpfx)%.so: $(objpfx)%.os + $(build-module) + +ifeq ($(build-shared),yes) others: $(objpfx)libpthread_nonshared.a endif @@ -185,6 +197,12 @@ tests-reverse += tst-cancel5 include ../Rules +ifeq (yes,$(build-shared)) +# Make sure these things are built in the `make lib' pass so they can be used +# to run programs during the `make others' pass. +lib-noranlib: $(addprefix $(objpfx),$(extra-objs)) +endif + # What we install as libpthread.so for programs to link against is in fact a # link script. It contains references for the various libraries we need. # The libpthread.so object is not complete since some functions are only @@ -220,6 +238,11 @@ CFLAGS-tst-unload.c += -DPREFIX=\"$(objpfx)\" tst-cancel7-ARGS = --command "$(built-program-cmd)" tst-umask1-ARGS = $(objpfx)tst-umask1.temp +$(objpfx)tst-atfork2: $(libdl) $(shared-thread-library) +LDFLAGS-tst-atfork2 = -rdynamic +tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace +$(objpfx)tst-atfork2mod.so: $(shared-thread-library) + extra-B-pthread.so = -B$(common-objpfx)nptl/ $(objpfx)libpthread.so: $(objpfx)crti.o $(objpfx)libpthread.so: +preinit += $(objpfx)crti.o @@ -245,6 +268,8 @@ $(addprefix $(objpfx), $(tests-reverse)): \ $(objpfx)../libc.so $(objpfx)libpthread.so \ $(objpfx)libpthread_nonshared.a $(addprefix $(objpfx),$(tests-static)): $(objpfx)libpthread.a + +$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so else $(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a endif @@ -270,7 +295,8 @@ $(objpfx)defs.h: $(objpfx)pt-initfini.s $(objpfx)crti.o: $(objpfx)crti.S $(objpfx)defs.h $(compile.S) -g0 $(ASFLAGS-.os) -o $@ -generated += crti.S defs.h pt-initfini.s +generated += crti.S defs.h pt-initfini.s $(objpfx)tst-atfork2.mtrace \ + $(addsuffix .so,$(strip $(modules-names))) $(objpfx)version.os: $(objpfx)banner.h $(objpfx)banner.h: Banner diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c index b643f89dfc..eba28064ea 100644 --- a/nptl/sysdeps/unix/sysv/linux/fork.c +++ b/nptl/sysdeps/unix/sysv/linux/fork.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -83,7 +83,7 @@ __libc_fork (void) /* Reset the file list. These are recursive mutexes. */ fresetlockfiles (); - /* We execute this even if the 'fork' call failed. */ + /* Reset locks in the I/O code. */ _IO_list_resetlock (); /* Run the handlers registered for the child. */ diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c index af567a0b18..7047d6a72a 100644 --- a/nptl/sysdeps/unix/sysv/linux/register-atfork.c +++ b/nptl/sysdeps/unix/sysv/linux/register-atfork.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -86,3 +86,37 @@ __register_atfork (prepare, parent, child, dso_handle) return 0; } libc_hidden_def (__register_atfork) + + +libc_freeres_fn (free_mem) +{ + /* Get the lock to not conflict with running forks. */ + lll_lock (__fork_lock); + + list_t *runp; + list_t *prevp; + + list_for_each_prev_safe (runp, prevp, &__fork_prepare_list) + { + list_del (runp); + + free (list_entry (runp, struct fork_handler, list)); + } + + list_for_each_prev_safe (runp, prevp, &__fork_parent_list) + { + list_del (runp); + + free (list_entry (runp, struct fork_handler, list)); + } + + list_for_each_prev_safe (runp, prevp, &__fork_child_list) + { + list_del (runp); + + free (list_entry (runp, struct fork_handler, list)); + } + + /* Release the lock. */ + lll_unlock (__fork_lock); +} diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c index 470f80d05c..7b3a785923 100644 --- a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c +++ b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -34,15 +34,27 @@ __unregister_atfork (dso_handle) list_for_each_prev_safe (runp, prevp, &__fork_prepare_list) if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) - list_del (runp); + { + list_del (runp); + + free (list_entry (runp, struct fork_handler, list)); + } list_for_each_prev_safe (runp, prevp, &__fork_parent_list) if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) - list_del (runp); + { + list_del (runp); + + free (list_entry (runp, struct fork_handler, list)); + } list_for_each_prev_safe (runp, prevp, &__fork_child_list) if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) - list_del (runp); + { + list_del (runp); + + free (list_entry (runp, struct fork_handler, list)); + } /* Release the lock. */ lll_unlock (__fork_lock); diff --git a/nptl/tst-atfork1.c b/nptl/tst-atfork1.c index 25bd3f2f09..b42ab42469 100644 --- a/nptl/tst-atfork1.c +++ b/nptl/tst-atfork1.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,10 +17,12 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <errno.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <sys/wait.h> static int val; @@ -67,6 +69,7 @@ static int do_test (void) { pid_t pid; + int status = 0; if (pthread_atfork (prepare1, parent1, child1) != 0) { @@ -94,6 +97,12 @@ do_test (void) printf ("expected val=%d, got %d\n", 24, val); exit (1); } + + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("waitpid failed"); + exit (1); + } } else { @@ -101,11 +110,11 @@ do_test (void) if (val != 80) { printf ("expected val=%d, got %d\n", 80, val); - exit (1); + exit (2); } } - return 0; + return status; } #define TEST_FUNCTION do_test () diff --git a/nptl/tst-atfork2.c b/nptl/tst-atfork2.c new file mode 100644 index 0000000000..f162f80e6b --- /dev/null +++ b/nptl/tst-atfork2.c @@ -0,0 +1,159 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <dlfcn.h> +#include <errno.h> +#include <mcheck.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> + + +/* Must be exported. */ +int val; + +static void +prepare (void) +{ + val *= 2; +} + +static void +parent (void) +{ + val += 4; +} + +static void +child (void) +{ + val += 8; +} + + +static int +do_test (void) +{ + mtrace (); + + if (pthread_atfork (prepare, parent, child) != 0) + { + puts ("do_test: atfork failed"); + exit (1); + } + + void *h = dlopen ("tst-atfork2mod.so", RTLD_LAZY); + if (h == NULL) + { + printf ("dlopen failed: %s\n", dlerror ()); + exit (1); + } + + /* First trial of fork. */ + pid_t pid = fork (); + if (pid == -1) + { + puts ("1st fork failed"); + exit (1); + } + + if (pid == 0) + { + /* Child. */ + if (val != 80) + { + printf ("1st: expected val=%d, got %d\n", 80, val); + exit (2); + } + + exit (0); + } + + /* Parent. */ + if (val != 24) + { + printf ("1st: expected val=%d, got %d\n", 24, val); + exit (1); + } + + int status; + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("1st waitpid failed"); + exit (1); + } + + if (status != 0) + exit (status); + + puts ("unloading now"); + + /* Unload the module. */ + if (dlclose (h) != 0) + { + puts ("dlclose failed"); + exit (1); + } + + puts ("2nd fork"); + + /* Second fork trial. */ + val = 1; + pid = fork (); + if (pid == -1) + { + puts ("2nd fork failed"); + exit (1); + } + + if (pid == 0) + { + /* Child. */ + if (val != 10) + { + printf ("2nd: expected val=%d, got %d\n", 10, val); + exit (3); + } + + exit (0); + } + + /* Parent. */ + if (val != 6) + { + printf ("2nd: expected val=%d, got %d\n", 6, val); + exit (1); + } + + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + { + puts ("2nd waitpid failed"); + exit (1); + } + + if (status != 0) + exit (status); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nptl/tst-atfork2mod.c b/nptl/tst-atfork2mod.c new file mode 100644 index 0000000000..a7fe68d244 --- /dev/null +++ b/nptl/tst-atfork2mod.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + + +extern int val; + + +static void +prepare (void) +{ + ++val; +} + +static void +parent (void) +{ + val *= 4; +} + +static void +child (void) +{ + val *= 8; +} + +static void +__attribute__ ((constructor)) +init (void) +{ + extern void *__dso_handle; + printf ("dsohandle = %p\n", __dso_handle); + + if (pthread_atfork (prepare, parent, child) != 0) + { + puts ("init: atfork failed"); + exit (1); + } +} |