rosbridge_library.internal.executor_helpers module

Helpers for serializing rclpy entity lifecycle with the node’s executor.

Creating or destroying entities (clients, action servers, subscriptions, publishers, …) on a node from a worker thread is not safe against a rclpy executor that is concurrently spinning the same node: the executor’s wait-set rebuild can race with the worker thread’s entity registration or teardown and leave the executor holding a handle whose underlying PyCapsule has been freed. The symptom is either a SIGSEGV inside rclpy or, less loudly, a later TypeError: Object of type 'NoneType' is not an instance of 'capsule' from the next binding call on the affected node.

The remedy used throughout this package — and consistent with the IncomingQueue fix in #1183 — is to route the lifecycle call through executor.create_task(...) so it is serialized with the executor’s own work. This module centralizes that pattern.

rosbridge_library.internal.executor_helpers.run_on_executor(node_handle: Node, fn: Callable[[], _T]) _T

Run fn() on the node’s executor thread synchronously and return its result.

Use this whenever a worker thread needs to create or destroy an rclpy entity (Client, ActionServer, Subscription, Publisher, …) on a node that an executor is concurrently spinning.

If the node has no attached executor (rare; mostly unit tests), the callable is invoked inline. Exceptions raised by fn are re-raised in the calling thread.

rosbridge_library.internal.executor_helpers.schedule_on_executor(node_handle: Node, fn: Callable[[], object]) None

Schedule fn() for execution on the node’s executor thread.

Fire-and-forget: the caller does not wait for completion. Falls back to invoking fn inline if the node has no attached executor.