Skip to content

Commit 8fb8b31

Browse files
Janosch MachowinskiJanosch Machowinski
authored andcommitted
fix(ClientGoalHandle): Made mutex recursive to prevent deadlocks
This prevents deadlocks in cases, were e.g. get_status() would be called on the handle in a callback of the handle. Signed-off-by: Janosch Machowinski <[email protected]>
1 parent fa732b9 commit 8fb8b31

File tree

2 files changed

+12
-12
lines changed

2 files changed

+12
-12
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::mutex handle_mutex_;
166+
std::recursive_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::mutex> guard(handle_mutex_);
62+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
73+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
85+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
93+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
101+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
109+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
117+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
125+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
133+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
143+
std::lock_guard<std::recursive_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::mutex> guard(handle_mutex_);
171+
std::lock_guard<std::recursive_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.");

0 commit comments

Comments
 (0)