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.
Change-Id: I0dfed30045a28551217ceac227d33b2e18894932
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index bf2a0f5..cf16c29 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -82,3 +82,21 @@
}
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 40978db..4600b33 100644
--- a/libc/malloc_debug/DebugData.h
+++ b/libc/malloc_debug/DebugData.h
@@ -82,6 +82,10 @@
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 45e6892..dcf0ede 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -58,6 +58,10 @@
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 4f86579..8562900 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -84,6 +84,28 @@
__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;
@@ -155,6 +177,9 @@
if (malloc_zygote_child == nullptr) {
return false;
}
+
+ InitAtfork();
+
g_malloc_zygote_child = malloc_zygote_child;
g_dispatch = malloc_dispatch;