diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | malloc/thread-m.h | 21 | ||||
-rw-r--r-- | nptl/ChangeLog | 9 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/fork.h | 9 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/register-atfork.c | 52 |
5 files changed, 85 insertions, 12 deletions
@@ -1,3 +1,9 @@ +2003-04-05 Ulrich Drepper <drepper@redhat.com> + + * malloc/thread-m.h [PTHREAD_MUTEX_INITIALIZER]: If + HAVE_register_atfork_malloc is defined use __register_atfork_malloc + instead of __register_atfork. + 2003-04-05 Jakub Jelinek <jakub@redhat.com> * stdio-common/reg-printf.c (__register_printf_function): Calloc diff --git a/malloc/thread-m.h b/malloc/thread-m.h index d65ba913b2..71409ebc0e 100644 --- a/malloc/thread-m.h +++ b/malloc/thread-m.h @@ -1,6 +1,6 @@ /* Basic platform-independent macro definitions for mutexes and thread-specific data. - Copyright (C) 1996,1997,1998,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1996-1998,2000,2001,2002,2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger <wg@malloc.de>, 2001. @@ -77,13 +77,24 @@ extern void *__dso_handle __attribute__ ((__weak__)); #include <fork.h> -#ifdef SHARED -# define thread_atfork(prepare, parent, child) \ - __register_atfork (prepare, parent, child, __dso_handle) +#ifdef HAVE_register_atfork_malloc +# ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork_malloc (prepare, parent, child, __dso_handle) +# else +# define thread_atfork(prepare, parent, child) \ + __register_atfork_malloc (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +# endif #else -# define thread_atfork(prepare, parent, child) \ +# ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +# else +# define thread_atfork(prepare, parent, child) \ __register_atfork (prepare, parent, child, \ &__dso_handle == NULL ? NULL : __dso_handle) +# endif #endif #elif defined(MUTEX_INITIALIZER) diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 7273ece303..c798977cc6 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,12 @@ +2003-04-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/register-atfork.c: Define malloc_prepare, + malloc_parent, and malloc_child statically. + (__register_atfork_malloc): New function. + (free_mem): Don't free any of the malloc_* variables on the list. + * sysdeps/unix/sysv/linux/fork.h: Declare __register_atfork_malloc. + Define HAVE_register_atfork_malloc. + 2003-04-04 Ulrich Drepper <drepper@redhat.com> * sysdeps/pthread/createthread.c (create_thread): Add some more diff --git a/nptl/sysdeps/unix/sysv/linux/fork.h b/nptl/sysdeps/unix/sysv/linux/fork.h index f3f4c38a55..e59ae87964 100644 --- a/nptl/sysdeps/unix/sysv/linux/fork.h +++ b/nptl/sysdeps/unix/sysv/linux/fork.h @@ -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. @@ -54,4 +54,9 @@ extern int __register_atfork (void (*__prepare) (void), void (*__parent) (void), void (*__child) (void), void *dso_handle); -libc_hidden_proto (__register_atfork) + +extern void __register_atfork_malloc (void (*prepare) (void), + void (*parent) (void), + void (*child) (void), + void *dso_handle) attribute_hidden; +#define HAVE_register_atfork_malloc diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c index 2f63c781ab..6dbc163175 100644 --- a/nptl/sysdeps/unix/sysv/linux/register-atfork.c +++ b/nptl/sysdeps/unix/sysv/linux/register-atfork.c @@ -89,7 +89,45 @@ __register_atfork (prepare, parent, child, dso_handle) return 0; } -libc_hidden_def (__register_atfork) + + +/* Three static memory blocks used when registering malloc. */ +static struct fork_handler malloc_prepare; +static struct fork_handler malloc_parent; +static struct fork_handler malloc_child; + + +void +attribute_hidden +__register_atfork_malloc (prepare, parent, child, dso_handle) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); + void *dso_handle; +{ + /* Pre-fork handler. */ + malloc_prepare.handler = prepare; + malloc_prepare.dso_handle = dso_handle; + + /* Parent handler. */ + malloc_parent.handler = parent; + malloc_parent.dso_handle = dso_handle; + + /* Child handler. */ + malloc_child.handler = child; + malloc_child.dso_handle = dso_handle; + + /* Get the lock to not conflict with running forks. */ + lll_lock (__fork_lock); + + /* Now that we have all the handlers allocate enqueue them. */ + list_add_tail (&malloc_prepare.list, &__fork_prepare_list); + list_add_tail (&malloc_parent.list, &__fork_parent_list); + list_add_tail (&malloc_child.list, &__fork_child_list); + + /* Release the lock. */ + lll_unlock (__fork_lock); +} libc_freeres_fn (free_mem) @@ -104,22 +142,26 @@ libc_freeres_fn (free_mem) { list_del (runp); - free (list_entry (runp, struct fork_handler, list)); + struct fork_handler *p = list_entry (runp, struct fork_handler, list); + if (p != &malloc_prepare) + free (p); } list_for_each_prev_safe (runp, prevp, &__fork_parent_list) { list_del (runp); - free (list_entry (runp, struct fork_handler, list)); + struct fork_handler *p = list_entry (runp, struct fork_handler, list); + if (p != &malloc_parent) + free (p); } list_for_each_prev_safe (runp, prevp, &__fork_child_list) { list_del (runp); - void *p = list_entry (runp, struct fork_handler, list); - if (p != (void *) &__pthread_child_handler) + struct fork_handler *p = list_entry (runp, struct fork_handler, list); + if (p != &__pthread_child_handler && p != &malloc_child) free (p); } |