ros_sugar.io.ipc#

Inter-process communication over local stream sockets.

Framing helpers shared by the robot plugin feedback bus and the external processors, and the server/client pair that lets a component in its own process call external processors living in the launcher process (multiprocess launch).

A frame is op (u8) | channel length (u16) | channel | data length (u32) | data.

The sockets live in Linux’s abstract namespace. Server checks the peer’s user on every connection to ensure correct permission.

Module Contents#

Classes#

ExternalProcessorServer

Serves external processors to components running in their own process.

ExternalProcessorClient

Calls one external processor served by an ExternalProcessorServer.

Functions#

abstract_addr

Linux abstract-namespace AF_UNIX address for name.

accept_from_own_user

Accept a connection when it comes from this user, else close it and return None

recv_exact

Read exactly n bytes from sock.

read_frame

Read one framed message. Returns (op, channel, data), None on EOF/error, or TIMEOUT when the socket is idle.

processor_id

Id of a component’s external processor, unique within a launch

API#

ros_sugar.io.ipc.abstract_addr(name: str) → str#

Linux abstract-namespace AF_UNIX address for name.

A leading NUL byte puts the socket in the abstract namespace: it has no filesystem entry and is reclaimed automatically when the socket closes

ros_sugar.io.ipc.accept_from_own_user(server_sock: socket.socket) → Optional[socket.socket]#

Accept a connection when it comes from this user, else close it and return None

ros_sugar.io.ipc.recv_exact(sock: socket.socket, n: int, allow_idle_timeout: bool = False)#

Read exactly n bytes from sock.

Returns the bytes on success, None on EOF/error. When allow_idle_timeout is set and a recv times out before any bytes have been buffered, returns TIMEOUT so the caller can keep waiting rather than treat the idle socket as closed. A mid-frame timeout always keeps waiting.

ros_sugar.io.ipc.read_frame(sock: socket.socket)#

Read one framed message. Returns (op, channel, data), None on EOF/error, or TIMEOUT when the socket is idle.

exception ros_sugar.io.ipc.ExternalProcessorError#

Bases: Exception

Calling an external processor in the launcher process failed

add_note()#
with_traceback()#
ros_sugar.io.ipc.processor_id(node_name: str, key: str, index: int) → str#

Id of a component’s external processor, unique within a launch

class ros_sugar.io.ipc.ExternalProcessorServer#

Serves external processors to components running in their own process.

Started in the launcher process. It listens on an abstract socket and serves each connection in its own thread, so a component process that is respawned connects again and is served.

property endpoint: Optional[str]#

Name of the socket components connect to

register(proc_id: str, func: Callable) → None#

Serve func under proc_id

start() → None#

Bind the socket and start accepting connections

close() → None#

Stop serving and close the socket. The socket’s name is free when this returns. The accept thread is woken and waited for.

class ros_sugar.io.ipc.ExternalProcessorClient(endpoint: str, proc_id: str, timeout: float)#

Calls one external processor served by an ExternalProcessorServer.

Calls are serialized, as they share one connection. After a failed call the connection is dropped, so a reply arriving late is never read as the reply to the next call, and the next call connects again.

connect() → None#

Connect to the server

call(kwargs: Dict, timeout: Optional[float] = None) → Any#

Call the processor with keyword arguments

Parameters:
  • kwargs (Dict) – Keyword arguments of the call

  • timeout (Optional[float]) – Time (s) to wait for the reply, defaults to the client timeout

Raises:

ExternalProcessorError – If the call fails or times out

Returns:

Output of the processor

Return type:

Any

close() → None#

Close the connection