1 //===-- enable_disable.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "gwp_asan/tests/harness.h"
10 
11 constexpr size_t Size = 100;
12 
TEST_F(DefaultGuardedPoolAllocatorDeathTest,Fork)13 TEST_F(DefaultGuardedPoolAllocatorDeathTest, Fork) {
14   void *P;
15   pid_t Pid = fork();
16   EXPECT_GE(Pid, 0);
17   if (Pid == 0) {
18     P = GPA.allocate(Size);
19     EXPECT_NE(P, nullptr);
20     memset(P, 0x42, Size);
21     GPA.deallocate(P);
22     _exit(0);
23   }
24   waitpid(Pid, nullptr, 0);
25   P = GPA.allocate(Size);
26   EXPECT_NE(P, nullptr);
27   memset(P, 0x42, Size);
28   GPA.deallocate(P);
29 
30   // fork should stall if the allocator has been disabled.
31   EXPECT_DEATH(
32       {
33         GPA.disable();
34         alarm(1);
35         Pid = fork();
36         EXPECT_GE(Pid, 0);
37       },
38       "");
39 }
40 
41 namespace {
42 pthread_mutex_t Mutex;
43 pthread_cond_t Conditional = PTHREAD_COND_INITIALIZER;
44 bool ThreadReady = false;
45 
enableMalloc(void * arg)46 void *enableMalloc(void *arg) {
47   auto &GPA = *reinterpret_cast<gwp_asan::GuardedPoolAllocator *>(arg);
48 
49   // Signal the main thread we are ready.
50   pthread_mutex_lock(&Mutex);
51   ThreadReady = true;
52   pthread_cond_signal(&Conditional);
53   pthread_mutex_unlock(&Mutex);
54 
55   // Wait for the malloc_disable & fork, then enable the allocator again.
56   sleep(1);
57   GPA.enable();
58 
59   return nullptr;
60 }
61 
TEST_F(DefaultGuardedPoolAllocator,DisableForkEnable)62 TEST_F(DefaultGuardedPoolAllocator, DisableForkEnable) {
63   pthread_t ThreadId;
64   EXPECT_EQ(pthread_create(&ThreadId, nullptr, &enableMalloc, &GPA), 0);
65 
66   // Do not lock the allocator right away, the other thread may need it to start
67   // up.
68   pthread_mutex_lock(&Mutex);
69   while (!ThreadReady)
70     pthread_cond_wait(&Conditional, &Mutex);
71   pthread_mutex_unlock(&Mutex);
72 
73   // Disable the allocator and fork. fork should succeed after malloc_enable.
74   GPA.disable();
75   pid_t Pid = fork();
76   EXPECT_GE(Pid, 0);
77   if (Pid == 0) {
78     void *P = GPA.allocate(Size);
79     EXPECT_NE(P, nullptr);
80     GPA.deallocate(P);
81     _exit(0);
82   }
83   waitpid(Pid, nullptr, 0);
84   EXPECT_EQ(pthread_join(ThreadId, 0), 0);
85 }
86 } // namespace
87