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

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


The following commit(s) were added to refs/heads/master by this push:
     new f0970ef5ff Avoid confusing AIO callback lifetime test (#13159)
f0970ef5ff is described below

commit f0970ef5ffb43782992917c5d30e767b0a02a945
Author: Brian Neradt <[email protected]>
AuthorDate: Wed May 13 16:22:08 2026 -0500

    Avoid confusing AIO callback lifetime test (#13159)
    
    Coverity reports the AIO callback lifetime regression test as a leak
    and bad free because the test heap-allocates an owner object whose
    member callback is destroyed indirectly during completion. The runtime
    behavior is intentional, but the ownership pattern makes the regression
    test look invalid to static analysis.
    
    This updates the fixture so the owner has normal stack lifetime and
    owns the callback through a unique_ptr. The completion handler still
    destroys the callback before AIOCallback::io_complete() returns,
    preserving the lifetime coverage while making the allocation and free
    visible to analysis.
---
 src/iocore/aio/unit_tests/test_AIOCallback.cc | 27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/iocore/aio/unit_tests/test_AIOCallback.cc 
b/src/iocore/aio/unit_tests/test_AIOCallback.cc
index f75335f764..39fc1dede1 100644
--- a/src/iocore/aio/unit_tests/test_AIOCallback.cc
+++ b/src/iocore/aio/unit_tests/test_AIOCallback.cc
@@ -23,6 +23,8 @@
 
 #include <catch2/catch_test_macros.hpp>
 
+#include <memory>
+
 #include "iocore/aio/AIO.h"
 #include "iocore/eventsystem/Event.h"
 
@@ -30,26 +32,27 @@ namespace
 {
 
 struct AIOCompletionOwner : Continuation {
-  AIOCallback callback;
-  bool       *completed = nullptr;
+  std::unique_ptr<AIOCallback> callback;
+  bool                        *completed = nullptr;
 
-  explicit AIOCompletionOwner(bool &completion_flag) : Continuation(nullptr), 
completed(&completion_flag)
+  explicit AIOCompletionOwner(bool &completion_flag)
+    : Continuation(nullptr), callback(std::make_unique<AIOCallback>()), 
completed(&completion_flag)
   {
     SET_HANDLER(&AIOCompletionOwner::handle_aio_complete);
 
-    callback.action           = this;
-    callback.aiocb.aio_nbytes = 0;
-    callback.aio_result       = 0;
+    callback->action           = this;
+    callback->aiocb.aio_nbytes = 0;
+    callback->aio_result       = 0;
   }
 
   int
   handle_aio_complete(int event, void *data)
   {
     CHECK(event == AIO_EVENT_DONE);
-    CHECK(data == &callback);
+    CHECK(data == callback.get());
 
     *completed = true;
-    delete this;
+    callback.reset();
     return EVENT_DONE;
   }
 };
@@ -84,11 +87,11 @@ struct DeletionTrackedAIOCallback : AIOCallback {
 
 } // namespace
 
-TEST_CASE("AIOCallback completion tolerates owner deletion", "[iocore][aio]")
+TEST_CASE("AIOCallback completion tolerates callback deletion", 
"[iocore][aio]")
 {
-  bool completed = false;
-  auto owner     = new AIOCompletionOwner(completed);
-  auto callback  = &owner->callback;
+  bool               completed = false;
+  AIOCompletionOwner owner(completed);
+  auto              *callback = owner.callback.get();
 
   // Without ASan, a broken implementation can still pass because the stale 
value of from_ts_api is typically false.
   CHECK(callback->io_complete(EVENT_NONE, nullptr) == EVENT_DONE);

Reply via email to