Repository navigation
Remote Debugging
Copper's remote debug API exposes a replaying application over Zenoh. A debugger such as Time Traveler can navigate the recorded timeline, replay CopperLists, inspect task state, query schemas, and read structured logs without adding ad hoc instrumentation to the runtime.
Replay binaries should use the standard CLI contract:
--debug-base <zenoh-prefix>
--log-base <recorded-log>
--replay-log-base <replay-output>
cu29::replay::ReplayCli provides this contract for a dedicated replay binary. Use ReplayArgs with #[command(flatten)] when the binary has additional application-specific arguments. Each replay-server process should write to its own replay log path.
Run the application's replay target with --debug-base, --log-base, and
--replay-log-base pointing to its Zenoh prefix, recording, and replay output.
See the remote debug session example for a runnable host server.
After session.open, a client can use:
| Area | Methods |
|---|---|
| Navigation |
nav.seek, nav.step, nav.replay
|
| Timeline |
timeline.get_cursor, timeline.get_cl, timeline.list
|
| State |
state.inspect, state.read, state.search
|
| Schema |
schema.get_stack, schema.get_type, schema.get_outputs
|
| Logs |
logs.strings, logs.list
|
A replay server permits one active debug session. While otherwise idle, the debugger sends a session-scoped health.ping every second. Any request carrying the active session_id also renews the lease. If no session-scoped request arrives for 3 seconds, the server closes the session automatically and another debugger can connect. A health.ping without session_id checks whether the server is reachable but does not renew the lease.
While the lease is active, a second session.open fails with SessionBusy. Run another replay-server process with a different --debug-base and --replay-log-base when two independent logs or timeline cursors must be inspected concurrently.
schema.get_outputs accepts separate page and field_page values so tools can page both output slots and large field catalogs.
Debug values preserve Rust values that plain JSON cannot represent directly. This includes 128-bit integers, non-finite floats, and maps with non-string keys. Schema descriptors also distinguish structs, tuple structs, tuples, lists, arrays, maps, enums, and CuArrayVec containers so inspectors do not have to infer those shapes from display strings.
CuHandle contents are deferred by default. A payload contains a small handle descriptor, but the debugger does not read or copy the backing buffer unless the request sets:
{
"include_handle_contents": true,
"output_indices": [0, 2]
}The selected contents are returned out of line in the response attachments array. Primitive buffers use raw little-endian bytes; other handle values use CBOR. Binary attachments require the CBOR wire codec. JSON requests that ask for attachments fail explicitly instead of converting the bytes into a large JSON array.
On Linux, the default local transport reserves a 1 GiB Zenoh shared-memory pool and sends replies of 256 KiB or larger through explicitly allocated SHM buffers. Startup checks both RLIMIT_MEMLOCK and available /dev/shm capacity. A large reply is rejected if it cannot use SHM; Copper will not silently copy it over the Unix socket.
Configure the shell that launches both Copper and the debugger before starting either process:
sudo prlimit --pid $$ --memlock=2147483648:2147483648
ulimit -l 2097152
df -h /dev/shmThe ulimit -l value is in KiB. A shell cannot raise its soft limit above its current hard limit, which is why changing only ulimit may fail. For a systemd service use LimitMEMLOCK=2G. For Docker, configure both memory locking and SHM capacity:
--ulimit memlock=2147483648:2147483648 --shm-size=2gTests and memory-constrained deployments can choose an explicit profile with RemoteDebugShmConfig, validate it with remote_debug_shm_preflight, pass it to RemoteDebugZenohServer::new_with_shm_config, and configure the client builder with the same profile.
Non-Linux platforms retain the existing 4 MiB pool and 3 KiB transport-optimization threshold. They do not run the Linux RLIMIT_MEMLOCK or /dev/shm checks.
Start
- Home
- Project Templates
- Copper Application Overview
- Build and Deploy a Copper Application
- Copper Configuration file Reference
- Task Automation with just
Concepts
- Copper Runtime Overview
- Copper Configuration and Mission Visualization
- Copper Tasks lifecycle overview
- Copper Bridge concept
- Resources
- Modular Configuration
Embedded
Reference
- Reading Unified Logs
- Remote Debugging
- SDK Features
- Copper Component Catalog
- FAQ
- Copper Release Notes
External