From 3ffcc74ca4a3185f8dc71a54f72f0cbdaab8051b Mon Sep 17 00:00:00 2001 From: Nuthatch Agent Date: Mon, 2 Nov 2026 11:33:19 -0800 Subject: [PATCH] Return NotFound when converting profiles collected with sampling disabled. When profile_sampling_interval() is 0, return nullptr from SnapshotCurrent, StartAllocationProfiling, StartLifetimeProfiling, and StartEventTracing so no sampling hooks are registered and the resulting Profile has type kDoNotUse. In MakeProfileProto, return NotFoundError when converting an empty kDoNotUse profile while GetProfileSamplingInterval() is 0. Co-authored-by: Chris Kennelly PiperOrigin-RevId: 1012323050 --- tcmalloc/internal/BUILD | 1 + tcmalloc/internal/CMakeLists.txt | 1 + tcmalloc/internal/profile_builder.cc | 4 ++++ tcmalloc/internal/profile_builder_test.cc | 18 ++++++++++++++++++ tcmalloc/tcmalloc.cc | 12 ++++++++++++ 5 files changed, 36 insertions(+) diff --git a/tcmalloc/internal/BUILD b/tcmalloc/internal/BUILD index 8aa66b1ae..bb3d562ec 100644 --- a/tcmalloc/internal/BUILD +++ b/tcmalloc/internal/BUILD @@ -1255,6 +1255,7 @@ cc_test( ":residency", "//tcmalloc:malloc_extension", "//tcmalloc/internal:profile_cc_proto", + "//tcmalloc/testing:testutil", "@com_google_absl//absl/base", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", diff --git a/tcmalloc/internal/CMakeLists.txt b/tcmalloc/internal/CMakeLists.txt index b6bc8e9ea..9a1cdf1fb 100644 --- a/tcmalloc/internal/CMakeLists.txt +++ b/tcmalloc/internal/CMakeLists.txt @@ -1288,6 +1288,7 @@ tcmalloc_cc_test( "tcmalloc::internal_residency" "tcmalloc::malloc_extension" "tcmalloc::tcmalloc" + "tcmalloc::testing_testutil" ) tcmalloc_cc_test( diff --git a/tcmalloc/internal/profile_builder.cc b/tcmalloc/internal/profile_builder.cc index 69a896655..74db047fe 100644 --- a/tcmalloc/internal/profile_builder.cc +++ b/tcmalloc/internal/profile_builder.cc @@ -30,6 +30,7 @@ #include "absl/types/span.h" #include "tcmalloc/internal/compressibility.h" #include "tcmalloc/internal/pageflags.h" +#include "tcmalloc/internal_malloc_extension.h" #include "tcmalloc/malloc_extension.h" #if defined(__linux__) @@ -882,6 +883,9 @@ absl::StatusOr> MakeProfileProto( const ::tcmalloc::Profile& profile, PageFlagsBase* pageflags, Residency* residency) { if (profile.Type() == ProfileType::kDoNotUse) { + if (MallocExtension::GetProfileSamplingInterval() == 0) { + return absl::NotFoundError("Profile sampling is disabled"); + } #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ defined(ABSL_HAVE_LEAK_SANITIZER) || \ defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) diff --git a/tcmalloc/internal/profile_builder_test.cc b/tcmalloc/internal/profile_builder_test.cc index e453311a6..5fd7fd341 100644 --- a/tcmalloc/internal/profile_builder_test.cc +++ b/tcmalloc/internal/profile_builder_test.cc @@ -55,6 +55,7 @@ #include "tcmalloc/internal/residency.h" #include "tcmalloc/internal_malloc_extension.h" #include "tcmalloc/malloc_extension.h" +#include "tcmalloc/testing/testutil.h" namespace tcmalloc { namespace tcmalloc_internal { @@ -1658,6 +1659,23 @@ TEST(BuildId, ZeroOneAndCorruptAlignment) { EXPECT_EQ(GetBuildId(&info), ""); } +TEST(ProfileBuilderTest, DisabledSamplingReturnsNotFound) { + if (MallocExtension::GetProfileSamplingInterval() < 0) { + GTEST_SKIP() << "TCMalloc is not linked in this build configuration"; + } + ScopedProfileSamplingInterval scoped_interval(0); + + Profile heap_profile = MallocExtension::SnapshotCurrent(ProfileType::kHeap); + EXPECT_EQ(heap_profile.Type(), ProfileType::kDoNotUse); + EXPECT_EQ(MakeProfileProto(heap_profile).status().code(), + absl::StatusCode::kNotFound); + + Profile alloc_profile = MallocExtension::StartAllocationProfiling().Stop(); + EXPECT_EQ(alloc_profile.Type(), ProfileType::kDoNotUse); + EXPECT_EQ(MakeProfileProto(alloc_profile).status().code(), + absl::StatusCode::kNotFound); +} + } // namespace } // namespace tcmalloc_internal } // namespace tcmalloc diff --git a/tcmalloc/tcmalloc.cc b/tcmalloc/tcmalloc.cc index a46da909c..9c737ebba 100644 --- a/tcmalloc/tcmalloc.cc +++ b/tcmalloc/tcmalloc.cc @@ -290,6 +290,9 @@ extern "C" size_t TCMalloc_Internal_GetStats(char* buffer, extern "C" const ProfileBase* MallocExtension_Internal_SnapshotCurrent( ProfileType type) { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } switch (type) { case ProfileType::kHeap: return DumpHeapProfile(tc_globals).release(); @@ -302,17 +305,26 @@ extern "C" const ProfileBase* MallocExtension_Internal_SnapshotCurrent( extern "C" AllocationProfilingTokenBase* MallocExtension_Internal_StartAllocationProfiling() { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } return new AllocationSample(&tc_globals.allocation_samples, absl::Now()); } extern "C" tcmalloc_internal::AllocationProfilingTokenBase* MallocExtension_Internal_StartLifetimeProfiling() { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } return new deallocationz::DeallocationSample(&tc_globals.deallocation_samples, deallocationz::Mode::kLifetimes); } extern "C" tcmalloc_internal::AllocationProfilingTokenBase* MallocExtension_Internal_StartEventTracing() { + if (Parameters::profile_sampling_interval() <= 0) { + return nullptr; + } return new deallocationz::DeallocationSample( &tc_globals.deallocation_samples, deallocationz::Mode::kEventTrace); }