mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00: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:
parent
2e79fa3ebc
commit
7dac9f3d90
@ -1,5 +1,13 @@
|
||||
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]
|
||||
* malloc/malloc.c (_int_realloc): Make error message clearer.
|
||||
|
||||
|
@ -27,7 +27,7 @@ all:
|
||||
dist-headers := malloc.h
|
||||
headers := $(dist-headers) obstack.h mcheck.h
|
||||
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
|
||||
tst-mallocstate tst-mcheck
|
||||
tst-mallocstate tst-mcheck tst-mallocfork
|
||||
test-srcs = tst-mtrace
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
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
|
||||
@ -223,7 +227,18 @@ ptmalloc_lock_all (void)
|
||||
|
||||
if(__malloc_initialized < 1)
|
||||
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;;) {
|
||||
(void)mutex_lock(&ar_ptr->mutex);
|
||||
ar_ptr = ar_ptr->next;
|
||||
@ -236,6 +251,8 @@ ptmalloc_lock_all (void)
|
||||
/* Only the current thread may perform malloc/free calls now. */
|
||||
tsd_getspecific(arena_key, save_arena);
|
||||
tsd_setspecific(arena_key, ATFORK_ARENA_PTR);
|
||||
out:
|
||||
++atfork_recursive_cntr;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -245,6 +262,8 @@ ptmalloc_unlock_all (void)
|
||||
|
||||
if(__malloc_initialized < 1)
|
||||
return;
|
||||
if (--atfork_recursive_cntr != 0)
|
||||
return;
|
||||
tsd_setspecific(arena_key, save_arena);
|
||||
__malloc_hook = save_malloc_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"
|
Loading…
Reference in New Issue
Block a user