ros2 / ros2/rclcpp

Service list is not refreshed after destroying the services and the executor is spinning in a different thread

Open
#2,138 3 comments 0 reactions 1 assignee View on GitHub

@mjcarroll is already working on this.

Since Apr 6, 2023.

Dominant language
C++
Stars
805
Forks
564
Avg merge
1d 17h
Merged PRs (30d)
27

Description

Bug report

For some reason, calling spin or spin_until_future_complete from a different thread (in this case, from an async task) does not refresh the service list after destroying the services. Calling spin_some in the same thread works (see the code below).

Required Info:

  • Operating System: Ubuntu 22.04

  • Installation type: Binaries (ROS humble):

ros-humble-rclcpp:
  Installed: 16.0.3-1jammy.20230302.174123
  • Version or commit hash:

  • DDS implementation: rmw_cyclonedds_rmw

  • Client library (if applicable): rclcpp

Steps to reproduce issue

Just run the following code.

#include <time.h>
#include <chrono>
#include <iostream>
#include <rclcpp/rclcpp.hpp>
#include <std_srvs/srv/empty.hpp>

int main(int argc, char** argv)
{
  rclcpp::init(argc, argv);
  auto node = std::make_shared<rclcpp::Node>("test_node");
  auto executor = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
  executor->add_node(node);
  auto fut = std::async(std::launch::async, [executor] { executor->spin(); });

  {
    RCLCPP_INFO(node->get_logger(), "Create service named /ack...");
    auto srv = node->create_service<std_srvs::srv::Empty>(
        "ack", [](const std_srvs::srv::Empty::Request::SharedPtr,
                  std_srvs::srv::Empty::Response::SharedPtr) {});
    while (rclcpp::ok() && node->get_service_names_and_types().count("/ack") == 0) {
      RCLCPP_INFO(node->get_logger(), "Waiting until service is listed in the graph...");
      std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
  }

  RCLCPP_INFO(node->get_logger(), "Waiting until service is destroyed...");
  node->get_node_graph_interface()->notify_graph_change();

  while (rclcpp::ok() && node->get_service_names_and_types().count("/ack") > 0) {
    // executor->spin_some(); // this works!
    RCLCPP_INFO(node->get_logger(), "Checking service does not exist...");
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  executor->cancel();
}

It used to pass in ROS foxy but now hangs on the second while loop in humble.

Expected behavior

Execution completes

Actual behavior

Execution hangs on the second loop (used to pass in foxy).

Additional information

Feature request

Feature description
Implementation considerations

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.