[PATCH] D72364: [scudo][standalone] Modify malloc_{enable,disable} wrt fork

Kostya Kortchinsky via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 8 13:00:50 PST 2020


cryptoad updated this revision to Diff 236894.
cryptoad added a comment.

Submitting this new design for consideration. I am working on adding
some tests but at least the code idea can get some feedback.

The point now is to do, as suggested by eugenis@ something like:
`atwork(disable, enable, enable)`

With the previous mutexes, a disable/fork/enable from other thread
would have deadlocked due to the mutex being held by disable in fork
so enable wouldn't fire.

I changed that to use a pthread conditional variable loop which should
allow to not deadlock in this situation (I am working on a test that
would catch that).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72364/new/

https://reviews.llvm.org/D72364

Files:
  compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
  compiler-rt/lib/scudo/standalone/wrappers_c.inc


Index: compiler-rt/lib/scudo/standalone/wrappers_c.inc
===================================================================
--- compiler-rt/lib/scudo/standalone/wrappers_c.inc
+++ compiler-rt/lib/scudo/standalone/wrappers_c.inc
@@ -141,11 +141,37 @@
   return 0;
 }
 
+static pthread_once_t SCUDO_PREFIX(OnceControl) = PTHREAD_ONCE_INIT;
+static pthread_mutex_t SCUDO_PREFIX(Mutex) = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t SCUDO_PREFIX(Conditional) = PTHREAD_COND_INITIALIZER;
+static bool SCUDO_PREFIX(Disabled) = false;
+
+INTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() {
+  pthread_mutex_lock(&SCUDO_PREFIX(Mutex));
+  SCUDO_ALLOCATOR.enable();
+  SCUDO_PREFIX(Disabled) = false;
+  pthread_cond_broadcast(&SCUDO_PREFIX(Conditional));
+  pthread_mutex_unlock(&SCUDO_PREFIX(Mutex));
+}
+
+static void SCUDO_PREFIX(setupAtFork)();
+
 INTERFACE WEAK void SCUDO_PREFIX(malloc_disable)() {
+  pthread_mutex_lock(&SCUDO_PREFIX(Mutex));
+  while (SCUDO_PREFIX(Disabled))
+    pthread_cond_wait(&SCUDO_PREFIX(Conditional), &SCUDO_PREFIX(Mutex));
+  CHECK_EQ(pthread_once(&SCUDO_PREFIX(OnceControl), SCUDO_PREFIX(setupAtFork)),
+           0);
   SCUDO_ALLOCATOR.disable();
+  SCUDO_PREFIX(Disabled) = true;
+  pthread_mutex_unlock(&SCUDO_PREFIX(Mutex));
 }
 
-INTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() { SCUDO_ALLOCATOR.enable(); }
+// Execute malloc_enable for a fork child.
+static void SCUDO_PREFIX(setupAtFork)() {
+  pthread_atfork(SCUDO_PREFIX(malloc_disable), SCUDO_PREFIX(malloc_enable),
+                 SCUDO_PREFIX(malloc_enable));
+}
 
 INTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, UNUSED int value) {
   if (param == M_DECAY_TIME) {
Index: compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
===================================================================
--- compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
+++ compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
@@ -310,4 +310,32 @@
   fclose(F);
   EXPECT_EQ(strncmp(Buffer, "<malloc version=\"scudo-", 23), 0);
 }
+
+TEST(ScudoWrappersCTest, MallocFork) {
+  void *P;
+  pid_t Pid = fork();
+  EXPECT_GE(Pid, 0);
+  if (Pid == 0) {
+    P = malloc(Size);
+    EXPECT_NE(P, nullptr);
+    memset(P, 0x42, Size);
+    free(P);
+    _exit(0);
+  }
+  waitpid(Pid, nullptr, 0);
+  P = malloc(Size);
+  EXPECT_NE(P, nullptr);
+  memset(P, 0x42, Size);
+  free(P);
+
+  // fork should stall if the allocator has been disabled.
+  EXPECT_DEATH(
+      {
+        malloc_disable();
+        alarm(1);
+        Pid = fork();
+        EXPECT_GE(Pid, 0);
+      },
+      "");
+}
 #endif


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72364.236894.patch
Type: text/x-patch
Size: 2597 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200108/a2f3874d/attachment.bin>


More information about the llvm-commits mailing list