diff --git a/rclpy/rclpy/executors.py b/rclpy/rclpy/executors.py index 5b94e3d36..d45d7aeba 100644 --- a/rclpy/rclpy/executors.py +++ b/rclpy/rclpy/executors.py @@ -520,9 +520,6 @@ def _wait_for_ready_callbacks( entity_count = NumberOfEntities( len(subscriptions), len(guards), len(timers), len(clients), len(services)) - for waitable in waitables: - entity_count += waitable.get_num_entities() - # Construct a wait set with _WaitSet() as wait_set, ExitStack() as context_stack: sub_capsules = [] @@ -560,6 +557,13 @@ def _wait_for_ready_callbacks( except InvalidHandle: entity_count.num_guard_conditions -= 1 + for waitable in waitables: + try: + context_stack.enter_context(waitable) + entity_count += waitable.get_num_entities() + except InvalidHandle: + pass + context_capsule = context_stack.enter_context(self._context.handle) _rclpy.rclpy_wait_set_init( wait_set, diff --git a/rclpy/rclpy/qos_event.py b/rclpy/rclpy/qos_event.py index 504a9ae90..a0e6022b3 100644 --- a/rclpy/rclpy/qos_event.py +++ b/rclpy/rclpy/qos_event.py @@ -177,6 +177,14 @@ def add_to_wait_set(self, wait_set): with self._event_handle as event_capsule: self._event_index = _rclpy.rclpy_wait_set_add_entity('event', wait_set, event_capsule) + def __enter__(self): + """Mark event as in-use to prevent destruction while waiting on it.""" + self._event_handle.__enter__() + + def __exit__(self, t, v, tb): + """Mark event as not-in-use to allow destruction after waiting on it.""" + self._event_handle.__exit__(t, v, tb) + def destroy(self): self._event_handle.destroy() diff --git a/rclpy/rclpy/waitable.py b/rclpy/rclpy/waitable.py index a42211ed4..fb70bb107 100644 --- a/rclpy/rclpy/waitable.py +++ b/rclpy/rclpy/waitable.py @@ -65,6 +65,14 @@ def __init__(self, callback_group): # List of Futures that have callbacks needing execution self._futures = [] + def __enter__(self): + """Implement to mark entities as in-use to prevent destruction while waiting on them.""" + pass + + def __exit__(self, t, v, tb): + """Implement to mark entities as not-in-use to allow destruction after waiting on them.""" + pass + def add_future(self, future): self._futures.append(future)