mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03:00
[BZ #838]
* malloc/arena.c (ptmalloc_lock_all): If global lock already taken by the same thread, just bump the counter. (ptmalloc_unlock_all): If counter for recursive locks hasn't reached zero, don't do anything else. * malloc/Makefile (tests): Add tst-mallocfork. * malloc/tst-mallocfork.c: New file.
This commit is contained in:
@ -1,5 +1,13 @@
|
|||||||
2005-09-26 Ulrich Drepper <drepper@redhat.com>
|
2005-09-26 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
[BZ #838]
|
||||||
|
* malloc/arena.c (ptmalloc_lock_all): If global lock already taken
|
||||||
|
by the same thread, just bump the counter.
|
||||||
|
(ptmalloc_unlock_all): If counter for recursive locks hasn't reached
|
||||||
|
zero, don't do anything else.
|
||||||
|
* malloc/Makefile (tests): Add tst-mallocfork.
|
||||||
|
* malloc/tst-mallocfork.c: New file.
|
||||||
|
|
||||||
[BZ #808]
|
[BZ #808]
|
||||||
* malloc/malloc.c (_int_realloc): Make error message clearer.
|
* malloc/malloc.c (_int_realloc): Make error message clearer.
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ all:
|
|||||||
dist-headers := malloc.h
|
dist-headers := malloc.h
|
||||||
headers := $(dist-headers) obstack.h mcheck.h
|
headers := $(dist-headers) obstack.h mcheck.h
|
||||||
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||||
tst-mallocstate tst-mcheck
|
tst-mallocstate tst-mcheck tst-mallocfork
|
||||||
test-srcs = tst-mtrace
|
test-srcs = tst-mtrace
|
||||||
|
|
||||||
distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \
|
distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \
|
||||||
|
@ -210,6 +210,10 @@ free_atfork(Void_t* mem, const Void_t *caller)
|
|||||||
(void)mutex_unlock(&ar_ptr->mutex);
|
(void)mutex_unlock(&ar_ptr->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Counter for number of times the list is locked by the same thread. */
|
||||||
|
static unsigned int atfork_recursive_cntr;
|
||||||
|
|
||||||
/* The following two functions are registered via thread_atfork() to
|
/* The following two functions are registered via thread_atfork() to
|
||||||
make sure that the mutexes remain in a consistent state in the
|
make sure that the mutexes remain in a consistent state in the
|
||||||
fork()ed version of a thread. Also adapt the malloc and free hooks
|
fork()ed version of a thread. Also adapt the malloc and free hooks
|
||||||
@ -223,7 +227,18 @@ ptmalloc_lock_all (void)
|
|||||||
|
|
||||||
if(__malloc_initialized < 1)
|
if(__malloc_initialized < 1)
|
||||||
return;
|
return;
|
||||||
(void)mutex_lock(&list_lock);
|
if (mutex_trylock(&list_lock))
|
||||||
|
{
|
||||||
|
Void_t *my_arena;
|
||||||
|
tsd_getspecific(arena_key, my_arena);
|
||||||
|
if (my_arena == ATFORK_ARENA_PTR)
|
||||||
|
/* This is the same thread which already locks the global list.
|
||||||
|
Just bump the counter. */
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* This thread has to wait its turn. */
|
||||||
|
(void)mutex_lock(&list_lock);
|
||||||
|
}
|
||||||
for(ar_ptr = &main_arena;;) {
|
for(ar_ptr = &main_arena;;) {
|
||||||
(void)mutex_lock(&ar_ptr->mutex);
|
(void)mutex_lock(&ar_ptr->mutex);
|
||||||
ar_ptr = ar_ptr->next;
|
ar_ptr = ar_ptr->next;
|
||||||
@ -236,6 +251,8 @@ ptmalloc_lock_all (void)
|
|||||||
/* Only the current thread may perform malloc/free calls now. */
|
/* Only the current thread may perform malloc/free calls now. */
|
||||||
tsd_getspecific(arena_key, save_arena);
|
tsd_getspecific(arena_key, save_arena);
|
||||||
tsd_setspecific(arena_key, ATFORK_ARENA_PTR);
|
tsd_setspecific(arena_key, ATFORK_ARENA_PTR);
|
||||||
|
out:
|
||||||
|
++atfork_recursive_cntr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -245,6 +262,8 @@ ptmalloc_unlock_all (void)
|
|||||||
|
|
||||||
if(__malloc_initialized < 1)
|
if(__malloc_initialized < 1)
|
||||||
return;
|
return;
|
||||||
|
if (--atfork_recursive_cntr != 0)
|
||||||
|
return;
|
||||||
tsd_setspecific(arena_key, save_arena);
|
tsd_setspecific(arena_key, save_arena);
|
||||||
__malloc_hook = save_malloc_hook;
|
__malloc_hook = save_malloc_hook;
|
||||||
__free_hook = save_free_hook;
|
__free_hook = save_free_hook;
|
||||||
|
52
malloc/tst-mallocfork.c
Normal file
52
malloc/tst-mallocfork.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* Derived from the test case in
|
||||||
|
http://sourceware.org/bugzilla/show_bug.cgi?id=838. */
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_handler (int signum)
|
||||||
|
{
|
||||||
|
pid_t child = fork ();
|
||||||
|
if (child == 0)
|
||||||
|
exit (0);
|
||||||
|
TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
pid_t parent = getpid ();
|
||||||
|
|
||||||
|
struct sigaction action;
|
||||||
|
sigemptyset (&action.sa_mask);
|
||||||
|
action.sa_handler = sig_handler;
|
||||||
|
|
||||||
|
malloc (sizeof (int));
|
||||||
|
|
||||||
|
if (sigaction (SIGALRM, &action, NULL) != 0)
|
||||||
|
{
|
||||||
|
puts ("sigaction failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a child that sends the signal to be caught. */
|
||||||
|
pid_t child = fork ();
|
||||||
|
if (child == 0)
|
||||||
|
{
|
||||||
|
if (kill (parent, SIGALRM) == -1)
|
||||||
|
perror ("kill");
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
Reference in New Issue
Block a user