mirror of
https://github.com/gperftools/gperftools
synced 2025-02-16 11:47:07 +00:00
issue-496: Fix possible deadlock in thread+fork
This patch adds a pthread_atfork handler to set the internal locks in consistent state.
This commit is contained in:
parent
73ccf4d1b9
commit
05c33f5308
11
configure
vendored
11
configure
vendored
@ -15114,6 +15114,17 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
# for turning off services when run as root
|
# for turning off services when run as root
|
||||||
|
for ac_func in fork
|
||||||
|
do :
|
||||||
|
ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork"
|
||||||
|
if test "x$ac_cv_func_fork" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_FORK 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# for the pthread_atfork setup
|
||||||
for ac_header in features.h
|
for ac_header in features.h
|
||||||
do :
|
do :
|
||||||
ac_fn_c_check_header_mongrel "$LINENO" "features.h" "ac_cv_header_features_h" "$ac_includes_default"
|
ac_fn_c_check_header_mongrel "$LINENO" "features.h" "ac_cv_header_features_h" "$ac_includes_default"
|
||||||
|
@ -134,6 +134,7 @@ AC_CHECK_TYPES([struct mallinfo],,, [#include <malloc.h>])
|
|||||||
AC_CHECK_TYPES([Elf32_Versym],,, [#include <elf.h>]) # for vdso_support.h
|
AC_CHECK_TYPES([Elf32_Versym],,, [#include <elf.h>]) # for vdso_support.h
|
||||||
AC_CHECK_FUNCS(sbrk) # for tcmalloc to get memory
|
AC_CHECK_FUNCS(sbrk) # for tcmalloc to get memory
|
||||||
AC_CHECK_FUNCS(geteuid) # for turning off services when run as root
|
AC_CHECK_FUNCS(geteuid) # for turning off services when run as root
|
||||||
|
AC_CHECK_FUNCS(fork) # for the pthread_atfork setup
|
||||||
AC_CHECK_HEADERS(features.h) # for vdso_support.h
|
AC_CHECK_HEADERS(features.h) # for vdso_support.h
|
||||||
AC_CHECK_HEADERS(malloc.h) # some systems define stuff there, others not
|
AC_CHECK_HEADERS(malloc.h) # some systems define stuff there, others not
|
||||||
AC_CHECK_HEADERS(sys/malloc.h) # where some versions of OS X put malloc.h
|
AC_CHECK_HEADERS(sys/malloc.h) # where some versions of OS X put malloc.h
|
||||||
|
@ -79,6 +79,16 @@ class CentralFreeList {
|
|||||||
// page full of 5-byte objects would have 2 bytes memory overhead).
|
// page full of 5-byte objects would have 2 bytes memory overhead).
|
||||||
size_t OverheadBytes();
|
size_t OverheadBytes();
|
||||||
|
|
||||||
|
// Lock/Unlock the internal SpinLock. Used on the pthread_atfork call
|
||||||
|
// to set the lock in a consistent state before the fork.
|
||||||
|
void Lock() {
|
||||||
|
lock_.Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unlock() {
|
||||||
|
lock_.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TransferCache is used to cache transfers of
|
// TransferCache is used to cache transfers of
|
||||||
// sizemap.num_objects_to_move(size_class) back and forth between
|
// sizemap.num_objects_to_move(size_class) back and forth between
|
||||||
|
@ -56,6 +56,9 @@
|
|||||||
/* Define to 1 if you have the <features.h> header file. */
|
/* Define to 1 if you have the <features.h> header file. */
|
||||||
#undef HAVE_FEATURES_H
|
#undef HAVE_FEATURES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fork' function. */
|
||||||
|
#undef HAVE_FORK
|
||||||
|
|
||||||
/* Define to 1 if you have the `geteuid' function. */
|
/* Define to 1 if you have the `geteuid' function. */
|
||||||
#undef HAVE_GETEUID
|
#undef HAVE_GETEUID
|
||||||
|
|
||||||
|
@ -39,6 +39,36 @@
|
|||||||
|
|
||||||
namespace tcmalloc {
|
namespace tcmalloc {
|
||||||
|
|
||||||
|
#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
|
||||||
|
// These following two functions are registered via pthread_atfork to make
|
||||||
|
// sure the central_cache locks remain in a consisten state in the forked
|
||||||
|
// version of the thread.
|
||||||
|
|
||||||
|
static void CentralCacheLockAll()
|
||||||
|
{
|
||||||
|
Static::pageheap_lock()->Lock();
|
||||||
|
for (int i = 0; i < kNumClasses; ++i)
|
||||||
|
Static::central_cache()[i].Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CentralCacheUnlockAll()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < kNumClasses; ++i)
|
||||||
|
Static::central_cache()[i].Unlock();
|
||||||
|
Static::pageheap_lock()->Unlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void SetupAtForkLocksHandler()
|
||||||
|
{
|
||||||
|
#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
|
||||||
|
pthread_atfork(CentralCacheLockAll, // parent calls before fork
|
||||||
|
CentralCacheUnlockAll, // parent calls after fork
|
||||||
|
CentralCacheUnlockAll); // child calls after fork
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
|
SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
|
||||||
SizeMap Static::sizemap_;
|
SizeMap Static::sizemap_;
|
||||||
CentralFreeListPadded Static::central_cache_[kNumClasses];
|
CentralFreeListPadded Static::central_cache_[kNumClasses];
|
||||||
@ -49,6 +79,7 @@ PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
|
|||||||
StackTrace* Static::growth_stacks_ = NULL;
|
StackTrace* Static::growth_stacks_ = NULL;
|
||||||
PageHeap* Static::pageheap_ = NULL;
|
PageHeap* Static::pageheap_ = NULL;
|
||||||
|
|
||||||
|
|
||||||
void Static::InitStaticVars() {
|
void Static::InitStaticVars() {
|
||||||
sizemap_.Init();
|
sizemap_.Init();
|
||||||
span_allocator_.Init();
|
span_allocator_.Init();
|
||||||
@ -61,6 +92,8 @@ void Static::InitStaticVars() {
|
|||||||
for (int i = 0; i < kNumClasses; ++i) {
|
for (int i = 0; i < kNumClasses; ++i) {
|
||||||
central_cache_[i].Init(i);
|
central_cache_[i].Init(i);
|
||||||
}
|
}
|
||||||
|
SetupAtForkLocksHandler();
|
||||||
|
|
||||||
// It's important to have PageHeap allocated, not in static storage,
|
// It's important to have PageHeap allocated, not in static storage,
|
||||||
// so that HeapLeakChecker does not consider all the byte patterns stored
|
// so that HeapLeakChecker does not consider all the byte patterns stored
|
||||||
// in is caches as pointers that are sources of heap object liveness,
|
// in is caches as pointers that are sources of heap object liveness,
|
||||||
|
Loading…
Reference in New Issue
Block a user