1596d0614SEvgenii Stepanov //===-- enable_disable.cpp --------------------------------------*- C++ -*-===//
2596d0614SEvgenii Stepanov //
3596d0614SEvgenii Stepanov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4596d0614SEvgenii Stepanov // See https://llvm.org/LICENSE.txt for license information.
5596d0614SEvgenii Stepanov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6596d0614SEvgenii Stepanov //
7596d0614SEvgenii Stepanov //===----------------------------------------------------------------------===//
8596d0614SEvgenii Stepanov
9596d0614SEvgenii Stepanov #include "gwp_asan/tests/harness.h"
10596d0614SEvgenii Stepanov
11596d0614SEvgenii Stepanov constexpr size_t Size = 100;
12596d0614SEvgenii Stepanov
TEST_F(DefaultGuardedPoolAllocatorDeathTest,Fork)13*dd1c4bd0SMitch Phillips TEST_F(DefaultGuardedPoolAllocatorDeathTest, Fork) {
14596d0614SEvgenii Stepanov void *P;
15596d0614SEvgenii Stepanov pid_t Pid = fork();
16596d0614SEvgenii Stepanov EXPECT_GE(Pid, 0);
17596d0614SEvgenii Stepanov if (Pid == 0) {
18596d0614SEvgenii Stepanov P = GPA.allocate(Size);
19596d0614SEvgenii Stepanov EXPECT_NE(P, nullptr);
20596d0614SEvgenii Stepanov memset(P, 0x42, Size);
21596d0614SEvgenii Stepanov GPA.deallocate(P);
22596d0614SEvgenii Stepanov _exit(0);
23596d0614SEvgenii Stepanov }
24596d0614SEvgenii Stepanov waitpid(Pid, nullptr, 0);
25596d0614SEvgenii Stepanov P = GPA.allocate(Size);
26596d0614SEvgenii Stepanov EXPECT_NE(P, nullptr);
27596d0614SEvgenii Stepanov memset(P, 0x42, Size);
28596d0614SEvgenii Stepanov GPA.deallocate(P);
29596d0614SEvgenii Stepanov
30596d0614SEvgenii Stepanov // fork should stall if the allocator has been disabled.
31596d0614SEvgenii Stepanov EXPECT_DEATH(
32596d0614SEvgenii Stepanov {
33596d0614SEvgenii Stepanov GPA.disable();
34596d0614SEvgenii Stepanov alarm(1);
35596d0614SEvgenii Stepanov Pid = fork();
36596d0614SEvgenii Stepanov EXPECT_GE(Pid, 0);
37596d0614SEvgenii Stepanov },
38596d0614SEvgenii Stepanov "");
39596d0614SEvgenii Stepanov }
40596d0614SEvgenii Stepanov
41596d0614SEvgenii Stepanov namespace {
42596d0614SEvgenii Stepanov pthread_mutex_t Mutex;
43596d0614SEvgenii Stepanov pthread_cond_t Conditional = PTHREAD_COND_INITIALIZER;
44596d0614SEvgenii Stepanov bool ThreadReady = false;
45596d0614SEvgenii Stepanov
enableMalloc(void * arg)46596d0614SEvgenii Stepanov void *enableMalloc(void *arg) {
47596d0614SEvgenii Stepanov auto &GPA = *reinterpret_cast<gwp_asan::GuardedPoolAllocator *>(arg);
48596d0614SEvgenii Stepanov
49596d0614SEvgenii Stepanov // Signal the main thread we are ready.
50596d0614SEvgenii Stepanov pthread_mutex_lock(&Mutex);
51596d0614SEvgenii Stepanov ThreadReady = true;
52596d0614SEvgenii Stepanov pthread_cond_signal(&Conditional);
53596d0614SEvgenii Stepanov pthread_mutex_unlock(&Mutex);
54596d0614SEvgenii Stepanov
55596d0614SEvgenii Stepanov // Wait for the malloc_disable & fork, then enable the allocator again.
56596d0614SEvgenii Stepanov sleep(1);
57596d0614SEvgenii Stepanov GPA.enable();
58596d0614SEvgenii Stepanov
59596d0614SEvgenii Stepanov return nullptr;
60596d0614SEvgenii Stepanov }
61596d0614SEvgenii Stepanov
TEST_F(DefaultGuardedPoolAllocator,DisableForkEnable)62596d0614SEvgenii Stepanov TEST_F(DefaultGuardedPoolAllocator, DisableForkEnable) {
63596d0614SEvgenii Stepanov pthread_t ThreadId;
64596d0614SEvgenii Stepanov EXPECT_EQ(pthread_create(&ThreadId, nullptr, &enableMalloc, &GPA), 0);
65596d0614SEvgenii Stepanov
66596d0614SEvgenii Stepanov // Do not lock the allocator right away, the other thread may need it to start
67596d0614SEvgenii Stepanov // up.
68596d0614SEvgenii Stepanov pthread_mutex_lock(&Mutex);
69596d0614SEvgenii Stepanov while (!ThreadReady)
70596d0614SEvgenii Stepanov pthread_cond_wait(&Conditional, &Mutex);
71596d0614SEvgenii Stepanov pthread_mutex_unlock(&Mutex);
72596d0614SEvgenii Stepanov
73596d0614SEvgenii Stepanov // Disable the allocator and fork. fork should succeed after malloc_enable.
74596d0614SEvgenii Stepanov GPA.disable();
75596d0614SEvgenii Stepanov pid_t Pid = fork();
76596d0614SEvgenii Stepanov EXPECT_GE(Pid, 0);
77596d0614SEvgenii Stepanov if (Pid == 0) {
78596d0614SEvgenii Stepanov void *P = GPA.allocate(Size);
79596d0614SEvgenii Stepanov EXPECT_NE(P, nullptr);
80596d0614SEvgenii Stepanov GPA.deallocate(P);
81596d0614SEvgenii Stepanov _exit(0);
82596d0614SEvgenii Stepanov }
83596d0614SEvgenii Stepanov waitpid(Pid, nullptr, 0);
84596d0614SEvgenii Stepanov EXPECT_EQ(pthread_join(ThreadId, 0), 0);
85596d0614SEvgenii Stepanov }
86596d0614SEvgenii Stepanov } // namespace
87