Skip to content

Commit 429a60a

Browse files
committed
Throw CancelledError into cancelled task
Signed-off-by: Nadav Elkabets <[email protected]>
1 parent e88f71a commit 429a60a

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

rclpy/rclpy/experimental/asyncio_executor.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ def __init__(self, timer: Timer, loop: asyncio.AbstractEventLoop, schedule_cb) -
132132
self._schedule_cb = schedule_cb
133133
self._loop = loop
134134
self._build_waiter()
135-
self._timer.set_on_reset_callback(self.on_reset)
136135

137136
def _build_waiter(self) -> None:
138137
self._waiter = _WaitHandler(
@@ -353,7 +352,7 @@ async def spin_once_async(
353352
try:
354353
await ready_task_getter
355354
except asyncio.CancelledError:
356-
return
355+
pass
357356
return
358357

359358
if self._shutdown_fut in done:

rclpy/rclpy/task.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from asyncio import CancelledError
1516
from enum import Enum
1617
import inspect
1718
import sys
@@ -278,7 +279,7 @@ def __init__(self,
278279
self._task_lock = threading.Lock()
279280
self._fut_waiter: Optional[Future] = None
280281

281-
def __call__(self) -> None:
282+
def __call__(self, *, should_cancel: bool = False) -> None:
282283
"""
283284
Run or resume a task.
284285
@@ -302,7 +303,10 @@ def __call__(self) -> None:
302303
# Execute a coroutine
303304
handler = self._handler
304305
try:
305-
future = handler.send(None)
306+
if should_cancel:
307+
future = handler.throw(CancelledError())
308+
else:
309+
future = handler.send(None)
306310
executor = self._executor()
307311
if executor and hasattr(executor, '_resume_task'):
308312
if future:
@@ -314,14 +318,19 @@ def __call__(self) -> None:
314318
# The coroutine finished; store the result
315319
self.set_result(e.value)
316320
self._complete_task()
321+
except CancelledError:
322+
super().cancel()
317323
except Exception as e:
318324
self.set_exception(e)
319325
self._complete_task()
320326
else:
321327
# Execute a normal function
322328
try:
323329
assert self._handler is not None and callable(self._handler)
324-
self.set_result(self._handler(*self._args, **self._kwargs))
330+
if should_cancel:
331+
super().cancel()
332+
else:
333+
self.set_result(self._handler(*self._args, **self._kwargs))
325334
except Exception as e:
326335
self.set_exception(e)
327336
self._complete_task()
@@ -333,7 +342,7 @@ def __call__(self) -> None:
333342
def __wake(self, fut: Future):
334343
self._fut_waiter = None
335344
if fut.cancelled():
336-
self.cancel()
345+
self(should_cancel=True)
337346
elif fut.exception() is not None:
338347
self.set_exception(fut.exception())
339348
else:
@@ -358,7 +367,4 @@ def cancel(self) -> None:
358367
self._fut_waiter.cancel()
359368
return
360369

361-
if self._pending() and inspect.iscoroutine(self._handler):
362-
self._handler.close()
363-
364-
super().cancel()
370+
self(should_cancel=True)

rclpy/test/test_task.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,23 @@ def test_executing(self) -> None:
205205
t = Task(lambda: None)
206206
self.assertFalse(t.executing())
207207

208+
def test_task_throws_cancelled_error_inside_coroutine_when_cancelled(self) -> None:
209+
did_throw = False
210+
211+
async def test_coro():
212+
try:
213+
await Future()
214+
except asyncio.CancelledError:
215+
nonlocal did_throw
216+
did_throw = True
217+
raise
218+
219+
t = Task(test_coro)
220+
t()
221+
t.cancel()
222+
self.assertTrue(t.cancelled())
223+
self.assertTrue(did_throw)
224+
208225

209226
class TestFuture(unittest.TestCase):
210227

0 commit comments

Comments
 (0)