| //===-- enable_disable.cpp --------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "gwp_asan/tests/harness.h" |
| |
| constexpr size_t Size = 100; |
| |
| TEST_F(DefaultGuardedPoolAllocatorDeathTest, Fork) { |
| void *P; |
| pid_t Pid = fork(); |
| EXPECT_GE(Pid, 0); |
| if (Pid == 0) { |
| P = GPA.allocate(Size); |
| EXPECT_NE(P, nullptr); |
| memset(P, 0x42, Size); |
| GPA.deallocate(P); |
| _exit(0); |
| } |
| waitpid(Pid, nullptr, 0); |
| P = GPA.allocate(Size); |
| EXPECT_NE(P, nullptr); |
| memset(P, 0x42, Size); |
| GPA.deallocate(P); |
| |
| // fork should stall if the allocator has been disabled. |
| EXPECT_DEATH( |
| { |
| GPA.disable(); |
| alarm(1); |
| Pid = fork(); |
| EXPECT_GE(Pid, 0); |
| }, |
| ""); |
| } |
| |
| namespace { |
| pthread_mutex_t Mutex; |
| pthread_cond_t Conditional = PTHREAD_COND_INITIALIZER; |
| bool ThreadReady = false; |
| |
| void *enableMalloc(void *arg) { |
| auto &GPA = *reinterpret_cast<gwp_asan::GuardedPoolAllocator *>(arg); |
| |
| // Signal the main thread we are ready. |
| pthread_mutex_lock(&Mutex); |
| ThreadReady = true; |
| pthread_cond_signal(&Conditional); |
| pthread_mutex_unlock(&Mutex); |
| |
| // Wait for the malloc_disable & fork, then enable the allocator again. |
| sleep(1); |
| GPA.enable(); |
| |
| return nullptr; |
| } |
| |
| TEST_F(DefaultGuardedPoolAllocator, DisableForkEnable) { |
| pthread_t ThreadId; |
| EXPECT_EQ(pthread_create(&ThreadId, nullptr, &enableMalloc, &GPA), 0); |
| |
| // Do not lock the allocator right away, the other thread may need it to start |
| // up. |
| pthread_mutex_lock(&Mutex); |
| while (!ThreadReady) |
| pthread_cond_wait(&Conditional, &Mutex); |
| pthread_mutex_unlock(&Mutex); |
| |
| // Disable the allocator and fork. fork should succeed after malloc_enable. |
| GPA.disable(); |
| pid_t Pid = fork(); |
| EXPECT_GE(Pid, 0); |
| if (Pid == 0) { |
| void *P = GPA.allocate(Size); |
| EXPECT_NE(P, nullptr); |
| GPA.deallocate(P); |
| _exit(0); |
| } |
| waitpid(Pid, nullptr, 0); |
| EXPECT_EQ(pthread_join(ThreadId, 0), 0); |
| } |
| } // namespace |