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

cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 90b623ebb75d485c0088e65c1db6bc2458e3cd09
Author: Brian Neradt <[email protected]>
AuthorDate: Tue May 12 11:07:09 2026 -0500

    Fix bg fill teardown crash in update_size_and_time_stats (#13114)
    
    Production crash logs show ink_assert(0) firing in
    HttpTransact::update_size_and_time_stats when an HTTP/2 stream close
    re-enters HttpSM after the user-agent side was detached for background
    fill. The server-to-cache tunnel should continue, but the stale
    user-agent event misses the VC table and falls through to the default
    tunnel handler, which tears down the SM with background_fill still
    STARTED.
    
    This ignores stale user-agent VIO and close events while a background
    fill tunnel is active, so tunnel_handler_server remains responsible for
    driving the fill to COMPLETED or ABORTED. This also keeps an
    unconditional kill_this cleanup as a last-resort guard to balance
    background_fill_current_count if any unexpected path still tears down
    mid-fill.
    
    (cherry picked from commit d366ab0feda439399bc32d8d3d2551492347fcb1)
---
 src/proxy/http/HttpSM.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc
index ac2e1b657c..7a9c3bc8a5 100644
--- a/src/proxy/http/HttpSM.cc
+++ b/src/proxy/http/HttpSM.cc
@@ -2678,11 +2678,47 @@ HttpSM::main_handler(int event, void *data)
     }
   }
 
+  // Is there an active background-fill tunnel?
+  // Background fill detaches the user-agent VC and lets the server/cache side
+  // finish the response body. An Http2Stream can still deliver a scheduled UA
+  // close/error callback after that detach, but the UA VIO no longer has a VC
+  // table entry. This predicate recognizes only those detached UA-side events
+  // so they do not fall through to the default tunnel handler and tear down 
the
+  // HttpSM before the active background-fill tunnel completes.
+  auto is_stale_bg_fill_ua_event = [&]() -> bool {
+    if (background_fill != BACKGROUND_FILL_STARTED || 
!tunnel.is_tunnel_alive() || _ua.get_txn() == nullptr) {
+      return false;
+    }
+
+    switch (event) {
+    case VC_EVENT_EOS:
+    case VC_EVENT_ERROR:
+    case VC_EVENT_INACTIVITY_TIMEOUT:
+    case VC_EVENT_ACTIVE_TIMEOUT:
+    case VC_EVENT_WRITE_READY:
+    case VC_EVENT_WRITE_COMPLETE:
+    case VC_EVENT_READ_READY:
+    case VC_EVENT_READ_COMPLETE:
+      break;
+    default:
+      return false;
+    }
+
+    if (data == nullptr) {
+      return true;
+    }
+
+    return static_cast<VIO *>(data)->vc_server == _ua.get_txn();
+  };
+
   if (vc_entry) {
     jump_point = (static_cast<VIO *>(data) == vc_entry->read_vio) ? 
vc_entry->vc_read_handler : vc_entry->vc_write_handler;
     ink_assert(jump_point != (HttpSMHandler) nullptr);
     ink_assert(vc_entry->vc != (VConnection *)nullptr);
     (this->*jump_point)(event, data);
+  } else if (is_stale_bg_fill_ua_event()) {
+    SMDbg(dbg_ctl_http, "ignoring stale %s event for closed user agent while 
background fill is active",
+          HttpDebugNames::get_event_name(event));
   } else {
     ink_assert(default_handler != (HttpSMHandler) nullptr);
     (this->*default_handler)(event, data);
@@ -7587,6 +7623,16 @@ HttpSM::kill_this()
   //   we must check it again
   if (kill_this_async_done == true) {
     pending_action = nullptr;
+
+    // This should only be a last-resort cleanup path. A background fill is
+    // normally driven to COMPLETED or ABORTED by tunnel_handler_server, but
+    // any unexpected teardown must still balance the active fill gauge before
+    // optional stats/logging run.
+    if (background_fill == BACKGROUND_FILL_STARTED) {
+      background_fill = BACKGROUND_FILL_ABORTED;
+      Metrics::Gauge::decrement(http_rsb.background_fill_current_count);
+    }
+
     if (t_state.http_config_param->enable_http_stats) {
       update_stats();
     }

Reply via email to