Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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.
  • Loading branch information
Ulrich Drepper committed Sep 27, 2005
1 parent 2e79fa3 commit 7dac9f3
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion malloc/Makefile
Expand Up @@ -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 \
Expand Down
21 changes: 20 additions & 1 deletion malloc/arena.c
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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;
Expand Down
52 changes: 52 additions & 0 deletions malloc/tst-mallocfork.c
@@ -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"

0 comments on commit 7dac9f3

Please sign in to comment.