aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2016-02-07 22:51:15 -0800
committerChristopher Ferris <cferris@google.com>2016-02-23 15:55:37 -0800
commitd863530eccceeae00c1c5d4968550a052f13ec2c (patch)
tree0bad17c0ee2adbb26def20fe758520d11b497e4f
parenta071f48b1f2088c4dd1a18dac58834e4488ac563 (diff)
downloadandroid_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.cpp18
-rw-r--r--libc/malloc_debug/DebugData.h4
-rw-r--r--libc/malloc_debug/TrackData.h4
-rw-r--r--libc/malloc_debug/malloc_debug.cpp25
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;