-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cancelling asynchronous tasks has no effect? #1099
Comments
Any updates here or plans to adjust the code to the suggested version? |
@weber-niklas i think noone is working on this at this moment, besides Foxy is already E.O.L, we probably need to check if the same issue can happen with rolling and available distros. i will try to take a look in this week. |
It's not fixed in rolling... rclpy/rclpy/rclpy/executors.py Line 612 in 53d7760
Also awaiting a cancelled task blocks forever, as the __await__ method returns only when the task is done.Lines 64 to 65 in 53d7760
|
I have created another a little more complex example illustrating the problem import rclpy
from rclpy.node import Node
from rclpy.task import Future
from rclpy.callback_groups import MutuallyExclusiveCallbackGroup
def sleep_async(node: Node, time: float) -> Future:
"""
Sleeps for a given amount of time.
Creates a timer with the sleep time as frequency and destroys it on the first callback.
args:
node: The node to sleep on. Future will be created with the nodes executor.
time: The time to sleep in seconds
returns:
A future that will be done after the given amount of time.
"""
future = Future(executor=node.executor)
timer = node.create_timer(timer_period_sec=time, callback=lambda: _timer_callback(future), callback_group=MutuallyExclusiveCallbackGroup())
def _timer_callback(future: Future):
future.set_result(None)
node.destroy_timer(timer)
return future
async def sleep(self, seconds):
for i in range(1, seconds+1):
await sleep_async(self, 1)
print(f"Slept for {i} seconds")
if __name__ == "__main__":
rclpy.init()
node = rclpy.create_node("test")
executor = rclpy.get_global_executor()
executor.add_node(node)
task = executor.create_task(sleep, node, 5)
task.cancel()
print(f"{task.cancelled()=}")
executor.spin_until_future_complete(task)
print(f"{task.done()=}")
print(f"{task.cancelled()=}") Expected output:
Actual output:
The task does not cancel, runs till completed and then overrides the cancellation when setting the result. |
ros2/rclpy#1099 Signed-off-by: Tomoya Fujita <[email protected]>
@tonygoldman @weber-niklas if you can share the feedback to #1377, that would be appreciated. |
Bug report
Required Info:
Steps to reproduce issue
Expected behavior
This should terminate immediately, raising a
CancelledError
or equivalentActual behavior
This runs forever
Additional information
This is related to #1098 , as I was experimenting with exceptions and asynchronous tasks. I was wondering what happens when you
await
a task that's cancelled. since inasyncio
it raises aCancelledError
. It turns out that inrclpy
it does call the done callbacks, but the task is not marked as done / doesn't raise.I'm guessing that we need to adjust this logic:
rclpy/rclpy/rclpy/task.py
Line 56 in f6d652f
To be something like:
But I'd like to hear the maintainers' opinion first!
The text was updated successfully, but these errors were encountered: