Copilot commented on code in PR #13747:
URL: https://github.com/apache/trafficserver/pull/13747#discussion_r4186886991


##########
src/mgmt/config/ConfigReloadTrace.cc:
##########
@@ -415,6 +418,7 @@ ConfigReloadProgress::check_progress(int /* etype */, void 
* /* data */)
       Dbg(dbg_ctl_config, "Reload task %s confirmed %.*s after grace period, 
stopping progress check.",
           _reload->get_token().c_str(), static_cast<int>(state_str.size()), 
state_str.data());
       _reload->log_reload_summary(current_state);
+      delete this;
       return EVENT_DONE;

Review Comment:
   Self-deletion is now performed in multiple branches, which makes it easier 
for future edits to accidentally access members after `delete this` or to 
introduce inconsistent stop behavior. Consider consolidating the stop path 
(e.g., a single exit branch or a small helper that performs any final 
logging/cancellation and then deletes) so the lifetime transition is 
centralized and harder to misuse.



##########
src/mgmt/config/ConfigReloadTrace.cc:
##########
@@ -404,6 +406,7 @@ ConfigReloadProgress::check_progress(int /* etype */, void 
* /* data */)
   Dbg(dbg_ctl_config, "Checking progress for reload task %s - descr: %s", 
_reload ? _reload->get_token().c_str() : "null",
       _reload ? _reload->get_description().c_str() : "null");
   if (_reload == nullptr) {
+    delete this;
     return EVENT_DONE;
   }

Review Comment:
   Self-deletion is now performed in multiple branches, which makes it easier 
for future edits to accidentally access members after `delete this` or to 
introduce inconsistent stop behavior. Consider consolidating the stop path 
(e.g., a single exit branch or a small helper that performs any final 
logging/cancellation and then deletes) so the lifetime transition is 
centralized and harder to misuse.



##########
src/mgmt/config/ConfigReloadTrace.cc:
##########
@@ -455,6 +459,7 @@ ConfigReloadProgress::check_progress(int /* etype */, void 
* /* data */)
     }
     _reload->mark_as_bad_state(buf);
     Dbg(dbg_ctl_config, "%s", buf.c_str());
+    delete this;
     return EVENT_DONE;
   }

Review Comment:
   Self-deletion is now performed in multiple branches, which makes it easier 
for future edits to accidentally access members after `delete this` or to 
introduce inconsistent stop behavior. Consider consolidating the stop path 
(e.g., a single exit branch or a small helper that performs any final 
logging/cancellation and then deletes) so the lifetime transition is 
centralized and harder to misuse.



##########
src/records/unit_tests/test_ConfigReloadProgress.cc:
##########
@@ -0,0 +1,88 @@
+/** @file
+
+  Unit tests for the ConfigReloadProgress checker's ownership of its reload 
task
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+
+#include "inkevent_test_fixtures.h"
+
+#include "iocore/eventsystem/Tasks.h"
+#include "mgmt/config/ConfigReloadTrace.h"
+#include "records/RecCore.h"
+#include "records/RecordsConfig.h"
+
+#include <chrono>
+#include <memory>
+#include <thread>
+
+namespace
+{
+// The checker runs on ET_TASK, so the test run needs task threads and the 
reload records.
+struct ReloadCheckerListener : inkevent_test::EventProcessorListener {
+  using EventProcessorListener::EventProcessorListener;
+
+  void
+  testRunStarting(Catch::TestRunInfo const &info) override
+  {
+    EventProcessorListener::testRunStarting(info);
+    LibRecordsConfigInit();
+    tasksProcessor.register_event_type();
+    tasksProcessor.start(1);
+  }
+};
+
+bool
+wait_for_sole_owner(ConfigReloadTaskPtr const &task, std::chrono::seconds 
timeout)
+{
+  auto const deadline = std::chrono::steady_clock::now() + timeout;
+  while (task.use_count() > 1) {
+    if (std::chrono::steady_clock::now() >= deadline) {
+      return false;
+    }
+    std::this_thread::sleep_for(std::chrono::milliseconds{50});
+  }
+  return true;
+}

Review Comment:
   The polling loop (50ms sleep) combined with multi-second deadlines makes 
these tests relatively slow and potentially flaky on loaded CI. Consider 
reducing the overall wait by configuring the progress checker 
interval/grace/timeout to smaller values within the test and/or using a shorter 
sleep with an upper-bounded backoff.



##########
src/records/unit_tests/test_ConfigReloadProgress.cc:
##########
@@ -0,0 +1,88 @@
+/** @file
+
+  Unit tests for the ConfigReloadProgress checker's ownership of its reload 
task
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+
+#include "inkevent_test_fixtures.h"
+
+#include "iocore/eventsystem/Tasks.h"
+#include "mgmt/config/ConfigReloadTrace.h"
+#include "records/RecCore.h"
+#include "records/RecordsConfig.h"
+
+#include <chrono>
+#include <memory>
+#include <thread>
+
+namespace
+{
+// The checker runs on ET_TASK, so the test run needs task threads and the 
reload records.
+struct ReloadCheckerListener : inkevent_test::EventProcessorListener {
+  using EventProcessorListener::EventProcessorListener;
+
+  void
+  testRunStarting(Catch::TestRunInfo const &info) override
+  {
+    EventProcessorListener::testRunStarting(info);
+    LibRecordsConfigInit();
+    tasksProcessor.register_event_type();
+    tasksProcessor.start(1);
+  }
+};
+
+bool
+wait_for_sole_owner(ConfigReloadTaskPtr const &task, std::chrono::seconds 
timeout)
+{
+  auto const deadline = std::chrono::steady_clock::now() + timeout;
+  while (task.use_count() > 1) {
+    if (std::chrono::steady_clock::now() >= deadline) {
+      return false;
+    }
+    std::this_thread::sleep_for(std::chrono::milliseconds{50});
+  }
+  return true;
+}
+} // namespace
+
+CATCH_REGISTER_LISTENER(ReloadCheckerListener)
+
+TEST_CASE("Progress checker releases a task confirmed terminal", 
"[config][reload][lifetime]")
+{
+  auto task = std::make_shared<ConfigReloadTask>("test-token-terminal", "main 
task", true, nullptr);
+  task->start_progress_checker();
+  REQUIRE(task.use_count() == 2);
+
+  task->mark_as_bad_state("forced");
+  // The first check runs after check_interval (2 s) and confirms the terminal 
state 5 s later.
+  REQUIRE(wait_for_sole_owner(task, std::chrono::seconds{15}));
+}
+
+TEST_CASE("Progress checker releases a task that timed out", 
"[config][reload][lifetime]")
+{
+  REQUIRE(RecSetRecordString(ConfigReloadProgress::RECORD_TIMEOUT.data(), 
"1s", REC_SOURCE_EXPLICIT) == REC_ERR_OKAY);
+
+  auto task = std::make_shared<ConfigReloadTask>("test-token-timeout", "main 
task", true, nullptr);
+  task->start_progress_checker();
+  REQUIRE(task.use_count() == 2);

Review Comment:
   This test mutates a global record (`RECORD_TIMEOUT`) but doesn’t restore its 
previous value. Even though this is a dedicated test binary today, restoring 
the prior value (or using an RAII guard) will prevent future test-order 
dependencies if more cases get added to this executable.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to