This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch stripe_destructor_debug
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit d81e3422b7c9dbd7934a60d2a231336ab1a5cbc9
Author: Bryan Call <[email protected]>
AuthorDate: Thu Dec 11 10:05:31 2025 -0800

    Add debug instrumentation to Stripe destructor
    
    Add debug logging, validation assertions, and memory poisoning to help
    track down intermittent heap corruption issues during cache cleanup.
    
    - Add Dbg() logging with pointer address, size, and allocation type
    - Add assertions to validate size is reasonable before freeing
    - Add memory poisoning (0xDE pattern) in DEBUG builds before free
    - Reset raw_dir_size to 0 after freeing
    
    This helps diagnose issues like "free(): corrupted unsorted chunks"
    that can occur intermittently during cache test cleanup.
---
 src/iocore/cache/Stripe.cc | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/iocore/cache/Stripe.cc b/src/iocore/cache/Stripe.cc
index c0c0723657..ebd98d0642 100644
--- a/src/iocore/cache/Stripe.cc
+++ b/src/iocore/cache/Stripe.cc
@@ -40,6 +40,7 @@ namespace
 {
 
 DbgCtl dbg_ctl_cache_init{"cache_init"};
+DbgCtl dbg_ctl_cache_free{"cache_free"};
 
 constexpr int 
DIRECTORY_FOOTER_SIZE{ROUND_TO_STORE_BLOCK(sizeof(StripeHeaderFooter))};
 
@@ -172,12 +173,26 @@ Stripe::_init_directory(std::size_t directory_size, int 
header_size, int footer_
 Stripe::~Stripe()
 {
   if (this->directory.raw_dir != nullptr) {
+    // Debug logging to track cleanup - helps correlate with crash location
+    Dbg(dbg_ctl_cache_free, "Stripe %s: freeing raw_dir=%p size=%zu huge=%s", 
hash_text.get() ? hash_text.get() : "(null)",
+        this->directory.raw_dir, this->directory.raw_dir_size, 
this->directory.raw_dir_huge ? "true" : "false");
+
+    // Validate that size is reasonable (catches corruption before free)
+    ink_assert(this->directory.raw_dir_size > 0);
+    ink_assert(this->directory.raw_dir_size < MAX_STRIPE_SIZE);
+
+#ifdef DEBUG
+    // Poison memory before freeing to help detect use-after-free
+    memset(this->directory.raw_dir, 0xDE, this->directory.raw_dir_size);
+#endif
+
     if (this->directory.raw_dir_huge) {
       ats_free_hugepage(this->directory.raw_dir, this->directory.raw_dir_size);
     } else {
       ats_free(this->directory.raw_dir);
     }
-    this->directory.raw_dir = nullptr;
+    this->directory.raw_dir      = nullptr;
+    this->directory.raw_dir_size = 0;
   }
 }
 

Reply via email to