Read, Write, and Rdwr are the three atomic 9P operations:
- Read: non-blocking read
- Write: non-blocking write (fire-and-forget)
- Rdwr: atomic write-then-read (blocking, produces result)
BlockOnce and Stream are special cases of Read.
Rdwr is its own primitive — not a variant of either.
Same pattern as BlockOnce: framework handles the blocking loop.
readFn takes a base string, returns (data, nextBase, error).
signal fires when new data may be available.
Chat stream handlers now use Stream(a.ChatRead, a.ChatSignal).
StreamRaw retained for custom handlers.
streamChat() in support.go is now dead code (replaced by ChatRead).
BlockOnce now takes a value-reader and a signal source. The framework
handles the blocking loop: read → compare hash to base → if different
return → else wait on signal or timeout.
On timeout (ctx.Done), returns empty (not error) so clients re-open
cleanly.
BlockOnceRaw retained for queue-style handlers (bypass/pending,
proc/wait) that manage their own blocking.
EventValue adapter wraps a <-chan Event into BlockOnce-compatible
(readFn, signalFn) pair via a thin goroutine.
Wire context cancellation through the toolsrv 9P server so that
canceling a CallTool context properly terminates the running tool.
Changes:
- virtfs: Add Close() to File interface with CloseFn for Request handlers
- toolsrv/p9.go: Handle requests concurrently to allow Tclunk during
blocking Twrite; call entry.Close() in handleClunk
- toolsrv/internal/server/proc.go: Check ctx.Done() while waiting for
tool completion in NewProc
- Integration tests for context cancellation chain
The cancellation chain: client cancels ctx → fid.Close() → Tclunk →
handleClunk calls entry.Close() → closeFn cancels reqCtx → NewProc
sees ctx.Done() and returns ctx.Err()
Remove RequestCtx variant - all Request handlers now take context.
This is required for proper cancellation of blocking operations
like tool execution when the client disconnects or stop is called.
- Add RequestCtx field to FsNodeDecl for handlers that need context
- Add RequestCtx() helper function in virtfs/decl.go
- Update builder.go to handle RequestCtx in validation and Open
- Use RequestCtx in toolsrv proc/new and proc/new.bg handlers
This allows the context to be cancelled when the 9P fid is closed,
enabling proper stop/interrupt of running tool calls.
The with* functional options and newTree constructor were private and
only used in two places (builder and tests). Replaced with direct
field assignment on &Tree{} literals. Less abstraction, same behavior.
Each() now returns []FsNodeDecl directly. The Binding type was a
redundant subset of FsNodeDecl with a slightly different Remove
signature. Dynamic entries are now expressed uniformly — Remove,
Rename, Children, Aliases all live on FsNodeDecl like everything else.
Also added: Alias() and RenameNode() options, DirNode accepts
[]FsNodeDecl for passing pre-built child slices.
Drop all references to generic context type parameter, Applier,
and type/function aliasing patterns. Document the actual API:
plain closures, pre-bound Children in Bindings, no generics.