--- contrib/libs/tcmalloc/tcmalloc/malloc_extension.cc (index) +++ contrib/libs/tcmalloc/tcmalloc/malloc_extension.cc (working tree) @@ -468,6 +468,20 @@ void MallocExtension::EnableForkSupport() { #endif } +static std::atomic SoftMemoryLimitHandler_; + +void MallocExtension::SetSoftMemoryLimitHandler(SoftMemoryLimitCallback* handler) { +#if ABSL_INTERNAL_HAVE_WEAK_MALLOCEXTENSION_STUBS + SoftMemoryLimitHandler_.store(handler); +#endif +} + +MallocExtension::SoftMemoryLimitCallback* MallocExtension::GetSoftMemoryLimitHandler() { +#if ABSL_INTERNAL_HAVE_WEAK_MALLOCEXTENSION_STUBS + return SoftMemoryLimitHandler_.load(); +#endif +} + void MallocExtension::SetSampleUserDataCallbacks( CreateSampleUserDataCallback create, CopySampleUserDataCallback copy, --- contrib/libs/tcmalloc/tcmalloc/malloc_extension.h (index) +++ contrib/libs/tcmalloc/tcmalloc/malloc_extension.h (working tree) @@ -475,6 +475,10 @@ class MallocExtension final { // Allocator will continue to function correctly in the child, after calling fork(). static void EnableForkSupport(); + using SoftMemoryLimitCallback = void(); + static void SetSoftMemoryLimitHandler(SoftMemoryLimitCallback* handler); + static SoftMemoryLimitCallback* GetSoftMemoryLimitHandler(); + using CreateSampleUserDataCallback = void*(); using CopySampleUserDataCallback = void*(void*); using DestroySampleUserDataCallback = void(void*); --- contrib/libs/tcmalloc/tcmalloc/page_allocator.cc (index) +++ contrib/libs/tcmalloc/tcmalloc/page_allocator.cc (working tree) @@ -151,6 +151,10 @@ void PageAllocator::ShrinkToUsageLimit() { warned = true; Log(kLogWithStack, __FILE__, __LINE__, "Couldn't respect usage limit of ", limit_, "and OOM is likely to follow."); + + if (auto* handler = MallocExtension::GetSoftMemoryLimitHandler()) { + (*handler)(); + } } bool PageAllocator::ShrinkHardBy(Length pages) {