From ae603dccd68512bb9760da654283fd3b26dc7961 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 | 22 +++++++++++++++++++ 1 file changed, 22 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 5966071d71..ae16c112ce 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 @@ -54,6 +54,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) @@ -305,9 +309,27 @@ 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, allocator_shim::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) }