Repository navigation
Conversation
subspace_server --channel_config=FILE reads a StaticChannelConfig in protobuf text format and creates its channels and multiplexers before the server accepts any clients, so a subscriber that starts first gets the full channel layout instead of a placeholder. With a config loaded, clients can use only the configured channels and the server's own /subspace/ChannelDirectory and /subspace/Statistics. The configured channels stay when they have no users, and their layout is fixed: publishers must be fixed size and match the configured slot size, number of slots, checksum size and metadata size. Channels recovered from a shadow must match the config. A multiplexer with no publishers now reports its slot size.
asil_client/ is a C++17 client for safety-related software. It shares unreliable, fixed-size channels with the standard clients through the same shared memory protocol, using only the standard library and POSIX. It is built without exceptions or RTTI, returns an error code from every operation, and makes no heap allocations. - Publishers support checksums, metadata and activation messages. Subscribers support kReadNext and kReadNewest, dropped message counts, checksum checking and activation messages. - The server handshake is behind the ServerConnection interface. PhaserServerConnection implements the standard protocol with phaser messages in fixed buffers, sent and received in protobuf wire format, so the server sees the same bytes as from the other clients. - Bazel, CMake and Soong build phaser and generate subspace_phaser from subspace.proto. Android CMake cross-compiles take a host protoc-gen-phaser in PHASER_PLUGIN_EXECUTABLE. - Bazel moves to Abseil 20250814.1, protobuf 33.4, cpp_toolbelt 2.1.6 and phaser 2.1.3, with cpp_toolbelt and phaser pinned by git_override until they are in the Bazel Central Registry. CMake uses the same commits. - layout_test checks the ASIL client's view of shared memory against common/channel.h. asil_client_test exchanges messages with the standard client in both directions, checks that setup and teardown make no heap allocations, and checks that an oversized request leaves the connection usable. It is skipped on memfd builds, which the ASIL client doesn't support yet.
The server now creates the message buffers of every static channel and multiplexer when it starts, through the same code as a standard first publisher, so subscribers can map them before any publisher exists. A static channel or multiplexer with use_split_buffers gets split buffers, which the server creates, and publishers whose split setting differs from the config are rejected. GetClientBuffersRequest can ask for one prefix or slot of a split buffer set. ASIL publishers and subscribers map all of a channel's shared memory in Open(), and publishing and reading make no shared memory calls. They map the channel's newest buffer; the resize, placeholder remap and 16-buffer table are gone. A subscriber on a channel without buffers gets kNoBuffers, and a message in a buffer created by a resize after the subscriber opened returns kBufferNotMapped. The ASIL client also supports split buffers, mapping each slot into an array the caller provides. Slots from a standard publisher's custom allocator are mapped through C map/unmap callbacks with a context. The ASIL client also gains reliable publishers and subscribers, virtual channels, multiple held messages, subscriber queues and the memfd backend, and the server checks fixed size and locality across the virtual channels of a multiplexer.
The standard C++ client now builds its server requests and responses as phaser messages, like the ASIL client. ServerWire in common/server_wire.h serializes requests and decodes responses for both, with growable buffers for the standard client and fixed buffers for the ASIL connection, which still makes no heap allocations. The bytes on the socket are unchanged. CMake now requires PHASER_PLUGIN_EXECUTABLE when cross-compiling, since the standard client needs subspace_phaser.
A static channel's layout comes from the server's config, so its publishers now set a server_defined option instead of the options that shape the shared memory. The server rejects a publisher on a static channel that leaves out server_defined or sets num_slots, slot_size, fixed_size, checksum_size, metadata_size, subscriber_queue_arena_size or use_split_buffers, and rejects server_defined on any other channel. CreatePublisherResponse now reports the channel's slot size, checksum size, metadata size, split buffer setting and fixed size, and a server_defined publisher takes its layout from them. The C++, C, Python, Rust and ASIL clients have the option and check it before asking the server. The C++ and Rust default checksum_size is now 0, which means 4 bytes, and a bridge publisher on a static channel is server defined.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This branch adds three things, one per commit:
--channel_config=FILE). The server creates a fixed set of channels and multiplexers before it accepts clients. Only those channels can be used, and their layout is fixed.asil_client/). A C++17 client for safety-related software, built with no exceptions or RTTI and no heap allocation. It shares channels with the standard clients through the same shared memory protocol. Its server handshake uses phaser messages in fixed buffers, sent in protobuf wire format.Open(), so publishing and reading make nommaporshm_opencalls. Split buffers are supported.Server changes
use_split_buffersin a static channel or multiplexer config gives it split buffers, which the server creates. A publisher whose split setting differs from the config is rejected.GetClientBuffersRequestcan fetch one prefix or slot of a split buffer set (filter_slot,is_prefix,slot_id). This keeps each response inside the ASIL client's 16 KB wire buffer.ASIL client
kReadNext/kReadNewest, drop counts and activation messages/dev/shmand memfdOpen()returnskNoBuffers.kBufferNotMapped.SplitSlotarray that the caller provides. Slots from a standard publisher's custom allocator are mapped through C map/unmap callbacks with a context pointer.See
docs/asil-client.mdfor details.Dependencies
The pinned phaser and cpp_toolbelt commits are in dallison/phaser#13 and dallison/cpp_toolbelt#29.
MODULE.bazelusesgit_overrideuntil those versions reach the Bazel Central Registry.Testing
bazelisk test --config=macos_arm64 //...: 28/28 pass.asil_layout_testandasil_client_testpass.//asil_client/...and//server/...pass with/dev/shmand with--config=linux_memfd.asil_client_test(34 tests) exchanges messages between the ASIL and standard clients in both directions. It covers server-created static buffers, split buffers, custom allocators, resized channels and the rejected cases.layout_testchecks the ASIL shared memory layout againstcommon/channel.h.