spin_until_future_complete may block forever if nothing wakes the executor after the future completes
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 805
- Forks
- 564
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 27
Description
Bug report
Required Info:
- Operating System:
- jammy
- Installation type:
- source
- Version or commit hash:
- 85a7046ac39bfc0d787ed2bbe62574424e31b871
- DDS implementation:
- Fast-DDS
- Client library (if applicable):
- rclcpp
Steps to reproduce issue
C++:
#include <iostream>
#include <thread>
#include <chrono>
#include "rclcpp/rclcpp.hpp"
void sleep_a_bit()
{
std::cerr << "Sleeping for 5 seconds\n";
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cerr << "Waking up and exiting function\n";
}
void rescue_callback()
{
std::cerr << "rescue timer ran\n";
}
int main(int argc, char ** argv)
{
rclcpp::init(argc, argv);
auto node = std::make_shared<rclcpp::Node>("rclcpp_spin_until_future_complete_blocked");
// Rescue timer will wake the executor, causing it to look at the future again
auto rescue_timer = rclcpp::create_timer(
node,
node->get_clock(),
rclcpp::Duration(10, 0),
std::bind(rescue_callback));
rclcpp::executors::SingleThreadedExecutor exe;
exe.add_node(node);
std::shared_future<void> script = std::async(std::launch::async, sleep_a_bit);
std::cerr << "About to sleep until future complete\n";
exe.spin_until_future_complete(script);
std::cerr << "Executor realized future is complete\n";
rclcpp::shutdown();
return 0;
}
CMake:
add_executable(rclcpp_spin_until_future_complete_blocked
src/rclcpp_spin_until_future_complete_blocked.cpp)
target_link_libraries(rclcpp_spin_until_future_complete_blocked
rclcpp::rclcpp)
Expected behavior
I would expect the future being completed would cause spin_until_future_complete() to return, and the program would shutdown without the timer callback running.
$ ./rclcpp_spin_until_future_complete_blocked
About to sleep until future complete
Sleeping for 5 seconds
Waking up and exiting function
Executor realized future is complete
Actual behavior
After the future completes, spin_until_future_complete() blocks for another 5 seconds until the timer callback is run.
$ ./rclcpp_spin_until_future_complete_blocked
About to sleep until future complete
Sleeping for 5 seconds
Waking up and exiting function
rescue timer ran
Executor realized future is complete
Additional information
A similar limitation exists in rclpy.
I thinkspin_until_future_complete() only returns immediately after completion if the future is completed in the callback of the same executor.
We should probably document it here.
This limitation is why the demo for lifecycle_service_client doesn't exit (related issue ros2/demos#504)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the executor behavior described in the supplied C++ reproduction, then read rclcpp/include/rclcpp/executors.hpp around lines 57-68. Compare the behavior with the lifecycle_service_client example linked in the issue and its rescue timer. Done means the future-completion behavior is addressed or clearly documented, with a regression test or reproduction result showing the expected return behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- robotics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100