Skip to content

Commit b14af74

Browse files
authored
try aborting before canceling 1st on dtor of ServerGoalHandle. (#2953)
* try aborting before canceling 1st on dtor of ServerGoalHandle. Signed-off-by: Tomoya Fujita <[email protected]> * address review comments from Copilot AI. Signed-off-by: Tomoya Fujita <[email protected]> * add missing header file and descriptions in docsection. Signed-off-by: Tomoya Fujita <[email protected]> --------- Signed-off-by: Tomoya Fujita <[email protected]>
1 parent 38f4073 commit b14af74

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

rclcpp_action/include/rclcpp_action/server_goal_handle.hpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
#include "action_msgs/msg/goal_status.hpp"
2626

27+
#include "rclcpp/logging.hpp"
28+
2729
#include "rclcpp_action/visibility_control.hpp"
2830
#include "rclcpp_action/types.hpp"
2931

@@ -103,11 +105,19 @@ class ServerGoalHandleBase
103105
_execute();
104106

105107
/// Transition the goal to canceled state if it never reached a terminal state.
108+
/// Returns true if transitioned to canceled, else false.
106109
/// \internal
107110
RCLCPP_ACTION_PUBLIC
108111
bool
109112
try_canceling() noexcept;
110113

114+
/// Transition the goal to aborted state if it never reached a terminal state.
115+
/// Returns true if transitioned to aborted, else false.
116+
/// \internal
117+
RCLCPP_ACTION_PUBLIC
118+
bool
119+
try_aborting() noexcept;
120+
111121
// End API for communication between ServerGoalHandleBase and ServerGoalHandle<>
112122
// -----------------------------------------------------------------------------
113123

@@ -243,11 +253,22 @@ class ServerGoalHandle : public ServerGoalHandleBase
243253

244254
virtual ~ServerGoalHandle()
245255
{
246-
// Cancel goal if handle was allowed to destruct without reaching a terminal state
247-
if (try_canceling()) {
248-
auto null_result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
249-
null_result->status = action_msgs::msg::GoalStatus::STATUS_CANCELED;
250-
on_terminal_state_(uuid_, null_result);
256+
try {
257+
// Abort goal if handle was allowed to destruct without reaching a terminal state
258+
if (try_aborting()) {
259+
auto null_result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
260+
null_result->status = action_msgs::msg::GoalStatus::STATUS_ABORTED;
261+
on_terminal_state_(uuid_, null_result);
262+
} else if (try_canceling()) {
263+
// Cancel goal if handle was allowed to destruct without reaching a terminal state
264+
auto null_result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
265+
null_result->status = action_msgs::msg::GoalStatus::STATUS_CANCELED;
266+
on_terminal_state_(uuid_, null_result);
267+
}
268+
} catch (const std::exception & ex) {
269+
RCLCPP_DEBUG(
270+
rclcpp::get_logger("rclcpp_action"),
271+
"Failed to abort/cancel goal handler in destructor: %s", ex.what());
251272
}
252273
}
253274

rclcpp_action/src/server_goal_handle.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include <memory>
16+
#include <mutex>
1617

1718
#include "rcl_action/action_server.h"
1819
#include "rcl_action/goal_handle.h"
@@ -135,6 +136,24 @@ ServerGoalHandleBase::try_canceling() noexcept
135136
return RCL_RET_OK == ret;
136137
}
137138

138-
return false;
139+
return is_cancelable;
140+
}
141+
142+
bool
143+
ServerGoalHandleBase::try_aborting() noexcept
144+
{
145+
std::lock_guard<std::mutex> lock(rcl_handle_mutex_);
146+
rcl_ret_t ret;
147+
// Check if the goal is abortable
148+
const bool is_abortable = rcl_action_goal_handle_is_abortable(rcl_handle_.get());
149+
if (is_abortable) {
150+
// Transition to ABORTED
151+
ret = rcl_action_update_goal_state(rcl_handle_.get(), GOAL_EVENT_ABORT);
152+
if (RCL_RET_OK != ret) {
153+
return false;
154+
}
155+
}
156+
157+
return is_abortable;
139158
}
140159
} // namespace rclcpp_action

rclcpp_action/test/test_server_goal_handle.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class FibonacciServerGoalHandle
4444

4545
bool try_cancel() {return try_canceling();}
4646

47+
bool try_abort() {return try_aborting();}
48+
4749
void cancel_goal() {_cancel_goal();}
4850
};
4951

@@ -132,6 +134,20 @@ TEST_F(TestServerGoalHandle, abort) {
132134
EXPECT_THROW(handle_->abort(result), rclcpp::exceptions::RCLError);
133135
}
134136

137+
TEST_F(TestServerGoalHandle, try_abort) {
138+
handle_->execute();
139+
test_msgs::action::Fibonacci::Result::SharedPtr result =
140+
std::make_shared<test_msgs::action::Fibonacci::Result>();
141+
EXPECT_TRUE(handle_->try_abort());
142+
EXPECT_FALSE(handle_->is_canceling());
143+
EXPECT_FALSE(handle_->is_active());
144+
EXPECT_FALSE(handle_->is_executing());
145+
146+
auto mock = mocking_utils::patch_and_return(
147+
"lib:rclcpp_action", rcl_action_update_goal_state, RCL_RET_ERROR);
148+
EXPECT_THROW(handle_->abort(result), rclcpp::exceptions::RCLError);
149+
}
150+
135151
TEST_F(TestServerGoalHandle, succeed) {
136152
handle_->execute();
137153
test_msgs::action::Fibonacci::Result::SharedPtr result =

0 commit comments

Comments
 (0)