Skip to content

refactor(fspy-shared): make the payload a borrowed view - #671

Draft
wan9chi wants to merge 1 commit into
agent/fspy-alloc-generic-channelfrom
agent/fspy-channel-conf-view
Draft

refactor(fspy-shared): make the payload a borrowed view#671
wan9chi wants to merge 1 commit into
agent/fspy-alloc-generic-channelfrom
agent/fspy-channel-conf-view

Conversation

@wan9chi

@wan9chi wan9chi commented Aug 14, 2026

Copy link
Copy Markdown
Member

Motivation

The end goal is a fully std-free preload, and the payload types were shaped against it: the channel configuration and every payload path crossed process boundaries as Box<IpcStr>, copied out of the deserialization buffer through the global allocator — on the attach path, under the loader lock on Windows.

Nothing needs to own payload fields. This makes Payload and EncodedPayload strictly borrowed views over storage their producer owns — the model the Windows preload already had with its 'static Detours page:

  • ChannelConf<'a> borrows its paths; channel() returns only the Receiver, and Receiver::conf() derives the serializable configuration from receiver-owned C strings.
  • decode_payload_from_env leaks its allocations into whichever allocator the caller passes — the allocator's lifetime bounds the payload's. The supervisor lends its session paths per spawn instead of cloning boxes.
  • The unix preload attaches with one page-backed bump (fspy_nostd_alloc::page_bump()), held in ManuallyDrop from the start: the payload's process-lifetime storage lands at the bump's base, the sender's temporary path decode runs inside Bump::scoped so the same chunk is reused and reclaimed, and the bump is never dropped. One mapping for the whole attach (a second only if the payload outgrows the chunk), no global allocator, and the single unsafeassume_process_lifetime — reasons directly against the ManuallyDrop declaration; scoped taking &mut self forces the promotion to happen before any temporary can exist. The copy out of the environment is deliberate — env memory is not stable storage. seccomp_payload stays owned until fspy_seccomp_unotify grows borrowed types.
  • The Windows preload deserializes its payload zero-copy from the static page and forwards those original bytes to grandchildren instead of re-serializing per spawn.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

fspy benchmark

linux

dynamic/launch             change  +1.42%  [ -3.42% ..  +8.49%]  overhead   +50.59%
dynamic/access             change  -2.70%  [-21.30% ..  +6.92%]  overhead    +7.26%
dynamic/access-relative    change  +1.49%  [ -1.83% ..  +3.39%]  overhead   +48.50%
static/launch              change  +0.56%  [ -5.89% ..  +7.71%]  overhead  +144.78%
static/access              change  -0.11%  [ -1.17% ..  +0.84%]  overhead  +826.91%
static/access-relative     change  +0.02%  [ -0.91% ..  +0.96%]  overhead +1334.11%

macos

dynamic/launch             change  -0.73%  [ -5.22% ..  +3.69%]  overhead  +218.90%
dynamic/access             change  +0.34%  [ -4.44% ..  +5.86%]  overhead    +4.50%
dynamic/access-relative    change  -0.22%  [ -3.14% ..  +4.16%]  overhead  +243.82%

windows

dynamic/launch             change  -0.14%  [ -2.67% ..  +3.28%]  overhead   +26.81%
dynamic/access             change  +0.00%  [ -1.10% ..  +1.26%]  overhead    +1.42%
dynamic/access-relative    change  -0.17%  [ -3.70% ..  +3.93%]  overhead    +1.53%

@wan9chi
wan9chi force-pushed the agent/fspy-channel-conf-view branch from ddd04dd to cd1446d Compare August 14, 2026 04:21
@wan9chi wan9chi changed the title refactor(fspy-shared): make ChannelConf a borrowed view refactor(fspy-shared): make the payload a borrowed view Aug 14, 2026
@wan9chi
wan9chi force-pushed the agent/fspy-channel-conf-view branch 7 times, most recently from eb1efd6 to fde03cd Compare August 14, 2026 07:46
@wan9chi
wan9chi changed the base branch from main to agent/fspy-alloc-generic-channel August 14, 2026 07:47
@wan9chi
wan9chi force-pushed the agent/fspy-channel-conf-view branch 2 times, most recently from 4ea95ea to d2b0d8e Compare August 14, 2026 08:07
The payload and its channel configuration are now views over storage
their producer owns, the model the Windows preload already had with its
static Detours page:

- ChannelConf borrows its two paths; channel() returns only the
  Receiver, and Receiver::conf() derives the configuration from
  receiver-owned C strings, with the lock path now stored beside the
  keeper path.
- The unix Payload and EncodedPayload borrow every path and the encoded
  string. The supervisor lends its session paths per spawn instead of
  cloning boxes. seccomp_payload stays owned until fspy_seccomp_unotify
  grows borrowed types.
- decode_payload_from_env leaks its allocations into whichever
  allocator the caller passes, whose lifetime bounds the payload.
- The unix preload attaches with one page-backed bump from
  fspy_nostd_alloc::page_bump(), held in ManuallyDrop from the start:
  the payload storage lands at its base, the sender's temporary path
  decode runs inside Bump::scoped so the same chunk is reused and
  reclaimed, and the never-dropped bump gives one mapping for the whole
  attach unless the payload outgrows the chunk, nothing from the global
  allocator, and no borrows into the mutable process environment.
  assume_process_lifetime documents the single unsafe step that names
  the leak.
- The Windows preload deserializes its payload zero-copy from the
  static page and forwards those original bytes to children instead of
  re-serializing per spawn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wan9chi
wan9chi force-pushed the agent/fspy-channel-conf-view branch from d2b0d8e to 4fa2c1a Compare August 14, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant