From 3e3f032b6f5e621b23edacfc1b24171f11d3a29e Mon Sep 17 00:00:00 2001 From: klzgrad Date: Sat, 8 Feb 2025 19:57:01 +0800 Subject: [PATCH] musl: allocator: Avoid deadlock in pthread_atfork Musl 1.2.3 and before call malloc() in pthread_atfork(), which may result in a deadlock: PartitionRoot::EnableThreadCacheIfSupported() ::partition_alloc::internal::ScopedGuard guard{lock_}; ThreadCache::Create(this); ThreadCache::ThreadCache() PlatformThread::CurrentId() InitAtFork::InitAtFork() pthread_atfork() malloc() ShimMalloc() PartitionAllocFunctionsInternal::Malloc() PartitionRoot::AllocInternal() PartitionRoot::AllocInternalNoHooks() PartitionRoot::RawAlloc() ::partition_alloc::internal::ScopedGuard guard{internal::PartitionRootLock(this)}; --- .../src/partition_alloc/partition_root.cc | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc b/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc index 47556e5b89..ba0ee790bb 100644 --- a/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc +++ b/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc @@ -52,6 +52,10 @@ #include #endif // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) +#if defined(__MUSL__) +#include "partition_alloc/shim/allocator_shim.h" +#endif + namespace partition_alloc::internal { #if PA_BUILDFLAG(RECORD_ALLOC_INFO) @@ -277,9 +281,25 @@ void PartitionAllocMallocInitOnce() { // However, no perfect solution really exists to make threads + fork() // cooperate, but deadlocks are real (and fork() is used in DEATH_TEST()s), // and other malloc() implementations use the same techniques. + +#if defined(__MUSL__) + allocator_shim::AllocatorDispatch d = + *allocator_shim::GetAllocatorDispatchChainHeadForTesting(); + d.alloc_function = +[](size_t size, AllocToken, void*) -> void* { + // The size of the scratch fits struct atfork_funcs in Musl pthread_atfork.c. + static char scratch[5 * sizeof(void*)]; + return size != sizeof(scratch) ? nullptr : scratch; + }; + allocator_shim::InsertAllocatorDispatch(&d); +#endif + int err = pthread_atfork(BeforeForkInParent, AfterForkInParent, AfterForkInChild); PA_CHECK(err == 0); + +#if defined(__MUSL__) + allocator_shim::RemoveAllocatorDispatchForTesting(&d); +#endif #endif // PA_BUILDFLAG(IS_LINUX) || PA_BUILDFLAG(IS_CHROMEOS) }