You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(fspy-shared): make the payload a borrowed view (#671)
## 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 path; `channel()` returns only the
`Receiver`, and `Receiver::conf()` derives the serializable
configuration from the C string the receiver's keeper owns. `sender()`
decodes the path transiently from a caller-provided allocator and drops
the decoded string before returning — a bump allocator gets the space
back, since the block is its most recent allocation.
- `encode_payload` and `decode_payload_from_env` are symmetric: both
take the allocator by value, leak the strings the payload views borrow
into it, and `A: 'a` bounds the result. The supervisor lends its session
paths per spawn and encodes into a spawn-scoped bumpalo `Bump`, freed
when the spawn returns, instead of assembling `EncodedPayload` by hand
from a scope-owned `BString`.
- The attach is **safe code end to end, with no lifetime promotion
anywhere**: the preload ctor houses one page-backed bump in a
`static_cell::StaticCell`, so its borrow is `'static` by construction
and `from_env(envs, allocator)` — by-value `impl Allocator + Clone + 'a`
— simply instantiates `Client<'a>` at `'static`. decode leaks the
payload into the allocator; the sender's temporary path decode comes
from the same allocator and is reclaimed on drop; no scope, no
transmute. `Send + Sync` assertions on `EncodedPayload<'static>` and
`Client<'static>` seal the view-only design — a retained allocator
handle is interior-mutable and would fail them — and since the bump is
`!Sync`, no safe code can stash its handle globally either: it dies with
the ctor's scope. The redundant macOS manual `Send`/`Sync` impls on
`Client` are deleted (auto-derivation now proves them), and
`page_bump()` returns the nameable `PageBump` so the static can be
declared. One mapping serves the whole attach (a second only if the
payload outgrows the chunk), no global allocator, and no borrows into
the mutable process environment — env memory is not stable storage, so
the value is copied out deliberately. `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](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
0 commit comments