From e6e96d79b39f4a08a770036c94d3aa290ac80bf0 Mon Sep 17 00:00:00 2001 From: Mike Kruskal Date: Thu, 16 Jul 2026 22:03:06 -0700 Subject: [PATCH] Fix a GCC race condition leading to crashes on shutdown PiperOrigin-RevId: 949359590 --- tcmalloc/static_vars.cc | 6 +++--- tcmalloc/static_vars.h | 23 ++++++++++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tcmalloc/static_vars.cc b/tcmalloc/static_vars.cc index e545f476c..baac988f8 100644 --- a/tcmalloc/static_vars.cc +++ b/tcmalloc/static_vars.cc @@ -106,9 +106,9 @@ ABSL_CONST_INIT NumaTopology Static::numa_topology_; ABSL_CONST_INIT GwpAsanState Static::gwp_asan_state_; ABSL_CONST_INIT Static::PerSizeClassCounts Static::per_size_class_counts_; -TCMALLOC_ATTRIBUTE_NO_DESTROY ABSL_CONST_INIT SystemAllocator< - NumaTopology, kNormalPartitions> - Static::system_allocator_{numa_topology_, kMinMmapAlloc}; +TCMALLOC_ATTRIBUTE_NO_DESTROY ABSL_CONST_INIT + Static::SystemAllocatorStorage Static::system_allocator_{numa_topology_, + kMinMmapAlloc}; // Force kInvalidSpan to be read-protected. Span contains a std::atomic, and // libc++'s std::atomic implementation contains a mutable field in one of its // implementation details. This prevents Span from being placed in a read-only diff --git a/tcmalloc/static_vars.h b/tcmalloc/static_vars.h index 391aba936..c30fd5d1b 100644 --- a/tcmalloc/static_vars.h +++ b/tcmalloc/static_vars.h @@ -115,7 +115,7 @@ class Static final { static SystemAllocator, kNormalPartitions>& system_allocator() { - return system_allocator_; + return system_allocator_.allocator; } static Arena& arena() { return arena_; } @@ -252,8 +252,25 @@ class Static final { static PageAllocatorStorage page_allocator_; static PageMap pagemap_; - ABSL_CONST_INIT static SystemAllocator< - NumaTopology, kNormalPartitions> + // Avoid destruction of SystemAllocator in a way that works with constinit and + // C++17. Once C++17 support is dropped this can be replaced with + // absl::NoDestructor. absl::NoDestructor uses a placement new, which doesn't + // work with constinit in C++17. Destruction is especially dangerous here + // because it can lead to race conditions and crashes on shutdown. + union SystemAllocatorStorage { + constexpr SystemAllocatorStorage( + const NumaTopology& topology, + size_t min_mmap_size) + : allocator(topology, min_mmap_size) {} + + ~SystemAllocatorStorage() {} + + SystemAllocator, + kNormalPartitions> + allocator; + }; + + TCMALLOC_ATTRIBUTE_NO_DESTROY ABSL_CONST_INIT static SystemAllocatorStorage system_allocator_; static ABSL_ATTRIBUTE_SECTION_VARIABLE(.data.rel.ro) const Span kInvalidSpan;