Fixes spin_until_future_complete removing node it didn't add#1316
Fixes spin_until_future_complete removing node it didn't add#1316sloretz merged 2 commits intoros2:rollingfrom
Conversation
fujitatomoya
left a comment
There was a problem hiding this comment.
does this really resolve the #1313 (comment)? i think you are using the same callback group, and rcl_wait with recursive executor spin. seems pretty much you are hitting the situation described in https://docs.ros.org/en/rolling/How-To-Guides/Using-callback-groups.html#avoiding-deadlocks?
even if that works, waiting on the future completion synchronously in the callback would block the other entities with the same callback group to be blocked, i would not think this is good design practice for the application.
i may be missing something, i would like to get more comments from others.
|
Looking at rclcpp clcpp/executors.hpp, there's a similar TODO to the issue I described. I'm not sure which version of test code you looked at, but this is what I used to validate the issue beforehand, and how to show it was fixed after. Looking at the original issue see the usage of fibonacci_action_server, fibonacci_action_hybrid, and ros2 action send_goal. The last version of the hybrid is below fibomnacci_action_hybrid.pyimport rclpy
from rclpy import Future
from rclpy.action import ActionServer, ActionClient
from rclpy.action.client import ClientGoalHandle
from rclpy.action.server import ServerGoalHandle
import rclpy.logging
from rclpy.node import Node
from action_tutorials_interfaces.action import Fibonacci
from rclpy.executors import ExternalShutdownException
class FibonacciActionServer(Node):
def __init__(self):
super().__init__("fibonacci_action_server")
# self.client_node = rclpy.create_node('fibonacci_action_server_client')
self._action_server = ActionServer(
self, Fibonacci, "some_action", self.execute_callback
)
self._action_client = ActionClient(
self, Fibonacci, "fibonacci"
)
def execute_callback(self, goal_handle: ServerGoalHandle):
self.get_logger().info("Requesting goal...")
request_future = self._action_client.send_goal_async(Fibonacci.Goal(order=goal_handle.request.order))
rclpy.spin_until_future_complete(self,request_future)
self.get_logger().info("Recieved request result...")
spin_handle: ClientGoalHandle = request_future.result()
result_future: Future = spin_handle.get_result_async()
rclpy.spin_until_future_complete(self,result_future)
self.get_logger().info("Recieved final result...")
result = Fibonacci.Result()
if not result_future.cancelled():
result = result_future.result().result
goal_handle.succeed()
return result
def main(args=None):
try:
with rclpy.init(args=args):
fibonacci_action_server = FibonacciActionServer()
rclpy.spin(fibonacci_action_server)
except (KeyboardInterrupt, ExternalShutdownException):
pass
if __name__ == '__main__':
main()
|
Closes rclpy:ros2#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com>
05f17ee to
f32a86c
Compare
|
@sloretz It seems we did talk about this issue before. Could you please follow up on it and give some comments? |
sloretz
left a comment
There was a problem hiding this comment.
The fix LGTM, but please use coroutines for waiting for results inside a callback #1313 (comment)
|
@Mergifyio update |
✅ Branch has been successfully updated |
|
Pulls: #1316 |
|
Thanks for the PR! |
|
@sloretz can this be back ported? |
|
@Mergifyio backport jazzy iron humble |
✅ Backports have been createdDetails
|
Closes rclpy:#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 47346ef)
Closes rclpy:#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 47346ef)
Closes rclpy:#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 47346ef)
Closes rclpy:#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 47346ef) Co-authored-by: Jonathan <jmblixt3@gmail.com>
Closes rclpy:#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 47346ef) Co-authored-by: Jonathan <jmblixt3@gmail.com>
Closes rclpy:#1313 Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor This aims to fix that by only removing the node from the executor if it wasn't already present Signed-off-by: Jonathan Blixt <jmblixt3@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 47346ef) Co-authored-by: Jonathan <jmblixt3@gmail.com>
Closes #1313
Current if spin_unitl_future_complete is called inside a nodes callback it removes the node from the executor
This results in any subsiquent waitables to never be checked by the node since the node is no longer in the executor
This aims to fix that by only removing the node from the executor if it wasn't already present