Skip to content

Commit b0a956b

Browse files
committed
Revert "fix(ClientGoalHandle): Made mutex recursive to prevent deadlocks (ros2#2267)"
This reverts commit a1a356c.
1 parent 9e4aaed commit b0a956b

File tree

3 files changed

+12
-92
lines changed

3 files changed

+12
-92
lines changed

rclcpp_action/include/rclcpp_action/client_goal_handle.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class ClientGoalHandle
163163
ResultCallback result_callback_{nullptr};
164164
int8_t status_{GoalStatus::STATUS_ACCEPTED};
165165

166-
std::recursive_mutex handle_mutex_;
166+
std::mutex handle_mutex_;
167167
};
168168
} // namespace rclcpp_action
169169

rclcpp_action/include/rclcpp_action/client_goal_handle_impl.hpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ template<typename ActionT>
5959
std::shared_future<typename ClientGoalHandle<ActionT>::WrappedResult>
6060
ClientGoalHandle<ActionT>::async_get_result()
6161
{
62-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
62+
std::lock_guard<std::mutex> guard(handle_mutex_);
6363
if (!is_result_aware_) {
6464
throw exceptions::UnawareGoalHandleError();
6565
}
@@ -70,7 +70,7 @@ template<typename ActionT>
7070
void
7171
ClientGoalHandle<ActionT>::set_result(const WrappedResult & wrapped_result)
7272
{
73-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
73+
std::lock_guard<std::mutex> guard(handle_mutex_);
7474
status_ = static_cast<int8_t>(wrapped_result.code);
7575
result_promise_.set_value(wrapped_result);
7676
if (result_callback_) {
@@ -82,55 +82,55 @@ template<typename ActionT>
8282
void
8383
ClientGoalHandle<ActionT>::set_feedback_callback(FeedbackCallback callback)
8484
{
85-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
85+
std::lock_guard<std::mutex> guard(handle_mutex_);
8686
feedback_callback_ = callback;
8787
}
8888

8989
template<typename ActionT>
9090
void
9191
ClientGoalHandle<ActionT>::set_result_callback(ResultCallback callback)
9292
{
93-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
93+
std::lock_guard<std::mutex> guard(handle_mutex_);
9494
result_callback_ = callback;
9595
}
9696

9797
template<typename ActionT>
9898
int8_t
9999
ClientGoalHandle<ActionT>::get_status()
100100
{
101-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
101+
std::lock_guard<std::mutex> guard(handle_mutex_);
102102
return status_;
103103
}
104104

105105
template<typename ActionT>
106106
void
107107
ClientGoalHandle<ActionT>::set_status(int8_t status)
108108
{
109-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
109+
std::lock_guard<std::mutex> guard(handle_mutex_);
110110
status_ = status;
111111
}
112112

113113
template<typename ActionT>
114114
bool
115115
ClientGoalHandle<ActionT>::is_feedback_aware()
116116
{
117-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
117+
std::lock_guard<std::mutex> guard(handle_mutex_);
118118
return feedback_callback_ != nullptr;
119119
}
120120

121121
template<typename ActionT>
122122
bool
123123
ClientGoalHandle<ActionT>::is_result_aware()
124124
{
125-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
125+
std::lock_guard<std::mutex> guard(handle_mutex_);
126126
return is_result_aware_;
127127
}
128128

129129
template<typename ActionT>
130130
bool
131131
ClientGoalHandle<ActionT>::set_result_awareness(bool awareness)
132132
{
133-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
133+
std::lock_guard<std::mutex> guard(handle_mutex_);
134134
bool previous = is_result_aware_;
135135
is_result_aware_ = awareness;
136136
return previous;
@@ -140,7 +140,7 @@ template<typename ActionT>
140140
void
141141
ClientGoalHandle<ActionT>::invalidate(const exceptions::UnawareGoalHandleError & ex)
142142
{
143-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
143+
std::lock_guard<std::mutex> guard(handle_mutex_);
144144
// Guard against multiple calls
145145
if (is_invalidated()) {
146146
return;
@@ -168,7 +168,7 @@ ClientGoalHandle<ActionT>::call_feedback_callback(
168168
RCLCPP_ERROR(rclcpp::get_logger("rclcpp_action"), "Sent feedback to wrong goal handle.");
169169
return;
170170
}
171-
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
171+
std::lock_guard<std::mutex> guard(handle_mutex_);
172172
if (nullptr == feedback_callback_) {
173173
// Normal, some feedback messages may arrive after the goal result.
174174
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp_action"), "Received feedback but goal ignores it.");

rclcpp_action/test/test_client.cpp

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -852,86 +852,6 @@ TEST_F(TestClientAgainstServer, async_cancel_some_goals_with_callback)
852852
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_CANCELED, goal_handle0->get_status());
853853
}
854854

855-
TEST_F(TestClientAgainstServer, deadlock_in_callbacks)
856-
{
857-
std::atomic<bool> feedback_callback_called = false;
858-
std::atomic<bool> response_callback_called = false;
859-
std::atomic<bool> result_callback_called = false;
860-
std::atomic<bool> no_deadlock = false;
861-
862-
std::thread tr = std::thread(
863-
[&]() {
864-
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
865-
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
866-
867-
ActionGoal goal;
868-
869-
using GoalHandle = rclcpp_action::ClientGoalHandle<ActionType>;
870-
rclcpp_action::Client<ActionType>::SendGoalOptions ops;
871-
ops.feedback_callback =
872-
[&feedback_callback_called](const GoalHandle::SharedPtr handle,
873-
ActionType::Feedback::ConstSharedPtr) {
874-
// call functions on the handle that acquire the lock
875-
handle->get_status();
876-
handle->is_feedback_aware();
877-
handle->is_result_aware();
878-
879-
feedback_callback_called = true;
880-
};
881-
ops.goal_response_callback = [&response_callback_called](
882-
const GoalHandle::SharedPtr & handle) {
883-
// call functions on the handle that acquire the lock
884-
handle->get_status();
885-
handle->is_feedback_aware();
886-
handle->is_result_aware();
887-
888-
response_callback_called = true;
889-
};
890-
ops.result_callback = [&result_callback_called](
891-
const GoalHandle::WrappedResult &) {
892-
result_callback_called = true;
893-
};
894-
895-
goal.order = 6;
896-
auto future_goal_handle = action_client->async_send_goal(goal, ops);
897-
dual_spin_until_future_complete(future_goal_handle);
898-
auto goal_handle = future_goal_handle.get();
899-
900-
ASSERT_TRUE(goal_handle);
901-
902-
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(2)));
903-
904-
auto result_future = action_client->async_get_result(goal_handle);
905-
dual_spin_until_future_complete(result_future);
906-
907-
EXPECT_TRUE(result_future.valid());
908-
auto result = result_future.get();
909-
910-
no_deadlock = true;
911-
});
912-
913-
auto start_time = std::chrono::system_clock::now();
914-
915-
while (std::chrono::system_clock::now() - start_time < std::chrono::milliseconds(2000) &&
916-
!no_deadlock)
917-
{
918-
std::this_thread::sleep_for(std::chrono::milliseconds(10));
919-
}
920-
921-
if (no_deadlock) {
922-
tr.join();
923-
} else {
924-
// In case of a failure, the thread is assumed to be in a deadlock.
925-
// We detach the thread so we don't block further tests.
926-
tr.detach();
927-
}
928-
929-
EXPECT_TRUE(no_deadlock);
930-
EXPECT_TRUE(response_callback_called);
931-
EXPECT_TRUE(result_callback_called);
932-
EXPECT_TRUE(feedback_callback_called);
933-
}
934-
935855
TEST_F(TestClientAgainstServer, send_rcl_errors)
936856
{
937857
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);

0 commit comments

Comments
 (0)