Fix robust mutex handling after fork

This commit is contained in:
Ulrich Drepper 2011-06-30 20:41:34 -04:00
parent 89f654c57b
commit 6f8326cacd
5 changed files with 66 additions and 15 deletions

View file

@ -1,3 +1,13 @@
2011-06-30 Ulrich Drepper <drepper@gmail.com>
* nptl-init.c (__nptl_set_robust): New function.
(pthread_functions): Add reference.
* npthreadP.h: Declare __nptl_set_robust.
* sysdeps/pthread/pthread-functions.h (pthread_functions): Add
ptr_set_robust member.
* sysdeps/unix/sysv/linux/fork.c: Call set_robust_list syscall in
child if threads are used.
2011-06-14 Andreas Jaeger <aj@suse.de>
* pthread_rwlock_init.c: Include <string.h> for memset declaration.

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc.
/* Copyright (C) 2002-2007, 2008, 2009, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -67,6 +67,13 @@ static const char nptl_version[] __attribute_used__ = VERSION;
extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
#endif
#ifdef SHARED
static
#else
extern
#endif
void __nptl_set_robust (struct pthread *);
#ifdef SHARED
static void nptl_freeres (void);
@ -130,7 +137,8 @@ static const struct pthread_functions pthread_functions =
.ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd,
.ptr__nptl_setxid = __nptl_setxid,
/* For now only the stack cache needs to be freed. */
.ptr_freeres = nptl_freeres
.ptr_freeres = nptl_freeres,
.ptr_set_robust = __nptl_set_robust
};
# define ptr_pthread_functions &pthread_functions
#else
@ -147,7 +155,17 @@ nptl_freeres (void)
__unwind_freeres ();
__free_stacks (0);
}
static
#endif
void
__nptl_set_robust (struct pthread *self)
{
INTERNAL_SYSCALL_DECL (err);
INTERNAL_SYSCALL (set_robust_list, err, 2, &self->robust_head,
sizeof (struct robust_list_head));
}
/* For asynchronous cancellation we use a signal. This is the handler. */

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc.
/* Copyright (C) 2002-2007, 2009, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -555,17 +555,20 @@ extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffe
/* Old cleanup interfaces, still used in libc.so. */
extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
void (*routine) (void *), void *arg);
void (*routine) (void *), void *arg);
extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
int execute);
int execute);
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
void (*routine) (void *), void *arg);
void (*routine) (void *), void *arg);
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
int execute);
int execute);
extern void __nptl_deallocate_tsd (void) attribute_hidden;
extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
#ifndef SHARED
extern void __nptl_set_robust (struct pthread *self);
#endif
extern void __free_stacks (size_t limit) attribute_hidden;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
/* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
@ -97,6 +97,7 @@ struct pthread_functions
void (*ptr__nptl_deallocate_tsd) (void);
int (*ptr__nptl_setxid) (struct xid_command *);
void (*ptr_freeres) (void);
void (*ptr_set_robust) (struct pthread *);
};
/* Variable in libc.so. */

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
/* Copyright (C) 2002, 2003, 2007, 2008, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@ -29,6 +29,7 @@
#include <ldsodefs.h>
#include <bits/stdio-lock.h>
#include <atomic.h>
#include <pthreadP.h>
unsigned long int *__fork_generation_pointer;
@ -86,8 +87,8 @@ __libc_fork (void)
just go away. The unloading code works in the order of the
list.
While executing the registered handlers we are building a
list of all the entries so that we can go backward later on. */
While executing the registered handlers we are building a
list of all the entries so that we can go backward later on. */
while (1)
{
/* Execute the handler if there is one. */
@ -154,6 +155,24 @@ __libc_fork (void)
GL(dl_cpuclock_offset) = now;
#endif
#ifdef __NR_set_robust_list
/* Initialize the robust mutex list which has been reset during
the fork. We do not check for errors since if it fails here
it failed at process start as well and noone could have used
robust mutexes. We also do not have to set
self->robust_head.futex_offset since we inherit the correct
value from the parent. */
# ifdef SHARED
if (__builtin_expect (__libc_pthread_functions_init, 0))
PTHFCT_CALL (ptr_set_robust, (self));
# else
extern __typeof (__nptl_set_robust) __nptl_set_robust
__attribute__((weak));
if (__builtin_expect (__nptl_set_robust != NULL, 0))
__nptl_set_robust (self);
# endif
#endif
/* Reset the file list. These are recursive mutexes. */
fresetlockfiles ();
@ -170,10 +189,10 @@ __libc_fork (void)
allp->handler->child_handler ();
/* Note that we do not have to wake any possible waiter.
This is the only thread in the new process. The count
may have been bumped up by other threads doing a fork.
We reset it to 1, to avoid waiting for non-existing
thread(s) to release the count. */
This is the only thread in the new process. The count
may have been bumped up by other threads doing a fork.
We reset it to 1, to avoid waiting for non-existing
thread(s) to release the count. */
allp->handler->refcntr = 1;
/* XXX We could at this point look through the object pool