about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nptl/ChangeLog16
-rw-r--r--nptl/Makefile28
-rw-r--r--nptl/sysdeps/unix/sysv/linux/fork.c4
-rw-r--r--nptl/sysdeps/unix/sysv/linux/register-atfork.c36
-rw-r--r--nptl/sysdeps/unix/sysv/linux/unregister-atfork.c20
-rw-r--r--nptl/tst-atfork1.c15
-rw-r--r--nptl/tst-atfork2.c159
-rw-r--r--nptl/tst-atfork2mod.c58
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);
+    }
+}