Skip to content

Commit 5f856b6

Browse files
Janosch MachowinskiJanosch Machowinski
authored andcommitted
fix: added workaround for call to double calls to take_data
This adds a workaround for a known bug in the executor in iron. Signed-off-by: Janosch Machowinski <[email protected]>
1 parent 469f5cd commit 5f856b6

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

rclcpp_action/src/client.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ class ClientBaseImpl
161161

162162
// next ready event for taking, will be set by is_ready and will be processed by take_data
163163
std::atomic<size_t> next_ready_event;
164+
// used to indicate that next_ready_event has no ready event for processing
165+
static constexpr size_t NO_EVENT_READY = std::numeric_limits<size_t>::max();
164166

165167
rclcpp::Context::SharedPtr context_;
166168
rclcpp::node_interfaces::NodeGraphInterface::WeakPtr node_graph_;
@@ -351,7 +353,7 @@ ClientBase::is_ready(rcl_wait_set_t * wait_set)
351353
}
352354
}
353355

354-
pimpl_->next_ready_event = std::numeric_limits<size_t>::max();
356+
pimpl_->next_ready_event = ClientBaseImpl::NO_EVENT_READY;
355357

356358
if (is_feedback_ready) {
357359
pimpl_->next_ready_event = static_cast<size_t>(EntityType::FeedbackSubscription);
@@ -647,10 +649,12 @@ std::shared_ptr<void>
647649
ClientBase::take_data()
648650
{
649651
// next_ready_event is an atomic, caching localy
650-
size_t next_ready_event = pimpl_->next_ready_event.exchange(std::numeric_limits<uint32_t>::max());
652+
size_t next_ready_event = pimpl_->next_ready_event.exchange(ClientBaseImpl::NO_EVENT_READY);
651653

652-
if (next_ready_event == std::numeric_limits<uint32_t>::max()) {
653-
throw std::runtime_error("Taking data from action client but nothing is ready");
654+
if (next_ready_event == ClientBaseImpl::NO_EVENT_READY) {
655+
// there is a known bug in iron, that take_data might be called multiple
656+
// times. Therefore instead of throwing, we just return a nullptr as a workaround.
657+
return nullptr;
654658
}
655659

656660
return take_data_by_entity_id(next_ready_event);
@@ -751,7 +755,9 @@ void
751755
ClientBase::execute(std::shared_ptr<void> & data_in)
752756
{
753757
if (!data_in) {
754-
throw std::invalid_argument("'data_in' is unexpectedly empty");
758+
// workaround, if take_data was called multiple timed, it returns a nullptr
759+
// normally we should throw here, but as an API stable bug fix, we just ignore this...
760+
return;
755761
}
756762

757763
std::shared_ptr<ClientBaseData> data_ptr = std::static_pointer_cast<ClientBaseData>(data_in);

rclcpp_action/src/server.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,10 @@ ServerBase::take_data()
273273
{
274274
size_t next_ready_event = pimpl_->next_ready_event.exchange(ServerBaseImpl::NO_EVENT_READY);
275275

276-
if (next_ready_event == ServerBaseImpl::NO_EVENT_READY;) {
277-
throw std::runtime_error("ServerBase::take_data() called but no data is ready");
276+
if (next_ready_event == ServerBaseImpl::NO_EVENT_READY) {
277+
// there is a known bug in iron, that take_data might be called multiple
278+
// times. Therefore instead of throwing, we just return a nullptr as a workaround.
279+
return nullptr;
278280
}
279281

280282
return take_data_by_entity_id(next_ready_event);
@@ -363,7 +365,9 @@ void
363365
ServerBase::execute(std::shared_ptr<void> & data_in)
364366
{
365367
if (!data_in) {
366-
throw std::runtime_error("ServerBase::execute: give data pointer was null");
368+
// workaround, if take_data was called multiple timed, it returns a nullptr
369+
// normally we should throw here, but as an API stable bug fix, we just ignore this...
370+
return;
367371
}
368372

369373
std::shared_ptr<ServerBaseData> data_ptr = std::static_pointer_cast<ServerBaseData>(data_in);

0 commit comments

Comments
 (0)