diff options
author | Colin Cross <ccross@android.com> | 2016-02-07 22:51:15 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2016-02-23 15:55:37 -0800 |
commit | d863530eccceeae00c1c5d4968550a052f13ec2c (patch) | |
tree | 0bad17c0ee2adbb26def20fe758520d11b497e4f | |
parent | a071f48b1f2088c4dd1a18dac58834e4488ac563 (diff) | |
download | android_bionic-d863530eccceeae00c1c5d4968550a052f13ec2c.tar.gz android_bionic-d863530eccceeae00c1c5d4968550a052f13ec2c.tar.bz2 android_bionic-d863530eccceeae00c1c5d4968550a052f13ec2c.zip |
malloc_debug: reset TrackData mutex after fork
Add a pthread_atfork handler to malloc_debug to lock the TrackData mutex
during fork and reset it in the child. Ensures that the TrackData is
consistent when forking from a multi-threaded process, and that the
mutex is in a defined state in the child.
Bug: 27208635
(cherry picked from commit 7a28a3cf1f8df36e30724e8b4021cddde0596118)
Change-Id: I84bc67be09b8b767e1cf2f14141e2ae8dc4fb462
-rw-r--r-- | libc/malloc_debug/DebugData.cpp | 18 | ||||
-rw-r--r-- | libc/malloc_debug/DebugData.h | 4 | ||||
-rw-r--r-- | libc/malloc_debug/TrackData.h | 4 | ||||
-rw-r--r-- | libc/malloc_debug/malloc_debug.cpp | 25 |
4 files changed, 51 insertions, 0 deletions
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp index 92b866d03..0447566b0 100644 --- a/libc/malloc_debug/DebugData.cpp +++ b/libc/malloc_debug/DebugData.cpp @@ -82,3 +82,21 @@ bool DebugData::Initialize() { } return true; } + +void DebugData::PrepareFork() { + if (track != nullptr) { + track->PrepareFork(); + } +} + +void DebugData::PostForkParent() { + if (track != nullptr) { + track->PostForkParent(); + } +} + +void DebugData::PostForkChild() { + if (track != nullptr) { + track->PostForkChild(); + } +} diff --git a/libc/malloc_debug/DebugData.h b/libc/malloc_debug/DebugData.h index 40978dbe3..4600b33bc 100644 --- a/libc/malloc_debug/DebugData.h +++ b/libc/malloc_debug/DebugData.h @@ -82,6 +82,10 @@ class DebugData { bool need_header() { return need_header_; } size_t extra_bytes() { return extra_bytes_; } + void PrepareFork(); + void PostForkParent(); + void PostForkChild(); + std::unique_ptr<BacktraceData> backtrace; std::unique_ptr<TrackData> track; std::unique_ptr<FrontGuardData> front_guard; diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h index 45e68927e..dcf0ede1a 100644 --- a/libc/malloc_debug/TrackData.h +++ b/libc/malloc_debug/TrackData.h @@ -58,6 +58,10 @@ class TrackData { void DisplayLeaks(DebugData& debug); + void PrepareFork() { pthread_mutex_lock(&mutex_); } + void PostForkParent() { pthread_mutex_unlock(&mutex_); } + void PostForkChild() { pthread_mutex_init(&mutex_, NULL); } + private: pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER; std::unordered_set<Header*> headers_; diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp index 0c0907d00..dcc6048f7 100644 --- a/libc/malloc_debug/malloc_debug.cpp +++ b/libc/malloc_debug/malloc_debug.cpp @@ -85,6 +85,28 @@ void* debug_valloc(size_t size); __END_DECLS // ------------------------------------------------------------------------ +static void InitAtfork() { + static pthread_once_t atfork_init = PTHREAD_ONCE_INIT; + pthread_once(&atfork_init, [](){ + pthread_atfork( + [](){ + if (g_debug != nullptr) { + g_debug->PrepareFork(); + } + }, + [](){ + if (g_debug != nullptr) { + g_debug->PostForkParent(); + } + }, + [](){ + if (g_debug != nullptr) { + g_debug->PostForkChild(); + } + } + ); + }); +} static void LogTagError(const Header* header, const void* pointer, const char* name) { ScopedDisableDebugCalls disable; @@ -156,6 +178,9 @@ bool debug_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_ if (malloc_zygote_child == nullptr) { return false; } + + InitAtfork(); + g_malloc_zygote_child = malloc_zygote_child; g_dispatch = malloc_dispatch; |