Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions e2e/cmd/envdsmoke/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ import (

const (
// envdPort is envd's fixed listener; the SDK derives its host from it.
envdPort = 49983
// readyWait bounds the wait for envd to answer after the claim.
envdPort = 49983
readyWait = 60 * time.Second
// claimTTL outlasts the run so a lease expiry cannot look like a relay fault.
claimTTL = 30 * time.Minute
Expand Down Expand Up @@ -105,8 +104,7 @@ func run(addr, token, template, wantVersion string, hold time.Duration) error {
return nil
}

// reportGuest asks the guest what it is running, over silkd — the native data
// plane, which must keep working alongside envd.
// reportGuest asks the guest what it runs over silkd, the native data plane that must keep working beside envd.
func reportGuest(ctx context.Context, sb *sandbox.Sandbox, wantVersion string) error {
version, err := sb.Exec(ctx, "/usr/local/bin/envd", "-version")
if err != nil {
Expand Down Expand Up @@ -221,8 +219,7 @@ func stepConnectH1(ctx context.Context, rt *harness.PortRelay, _ *sandbox.Sandbo
return nil
}

// stepProcessStart spawns through envd's process service, the half the image runs with
// -no-cgroups, and reads its Connect server stream back over HTTP/1.1.
// stepProcessStart spawns through envd's process service, which the image runs with -no-cgroups, and reads its Connect server stream back.
func stepProcessStart(ctx context.Context, rt *harness.PortRelay, _ *sandbox.Sandbox) error {
headers := http.Header{
contentType: []string{"application/connect+json"},
Expand Down
7 changes: 2 additions & 5 deletions e2e/cmd/portsmoke/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ const (
// halfClosePort greets and shuts its write side, then keeps reading.
halfClosePort = 49984
// deadPort has no listener, so silkd's connect refusal must surface as 502.
deadPort = 49985
// listenerReadyWait bounds the wait for the in-guest listener to bind.
deadPort = 49985
listenerReadyWait = 20 * time.Second
// guestServerPath is where the uploaded listener lands in the guest.
guestServerPath = "/usr/local/bin/guestserver"
guestServerPath = "/usr/local/bin/guestserver"
// claimTTL outlasts the run; the node default would reap the sandbox mid-test.
claimTTL = 30 * time.Minute
)
Expand Down Expand Up @@ -167,7 +165,6 @@ func stepHTTP2(ctx context.Context, rt *harness.PortRelay, _ *sandbox.Sandbox) e
return wantReport(string(out), "proto=2", "method=POST")
}

// wantReport asserts guestserver reported each expected line.
func wantReport(body string, want ...string) error {
for _, line := range want {
if !strings.Contains(body, line) {
Expand Down
9 changes: 3 additions & 6 deletions mcp/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ var (
}
)

// tool binds one MCP tool's spec to its handler, so a tool can never exist
// in the listing without a dispatch entry.
// tool binds one MCP tool's spec to its handler, so a tool can never exist in the listing without a dispatch entry.
type tool struct {
name string
description string
Expand Down Expand Up @@ -135,8 +134,7 @@ func (a sandboxArg) id() string { return a.SandboxID }

type sandboxIDer interface{ id() string }

// parseAndBox decodes a tool's arguments and resolves their sandbox_id to a
// live handle — the prologue every sandbox-scoped tool shares.
// parseAndBox decodes a tool's arguments and resolves their sandbox_id to a live handle, the prologue every sandbox-scoped tool shares.
func parseAndBox[T sandboxIDer](s *server, raw json.RawMessage) (T, *sandbox.Sandbox, error) {
var args T
if err := parse(raw, &args); err != nil {
Expand Down Expand Up @@ -450,8 +448,7 @@ func (s *server) boxArg(raw json.RawMessage) (*sandbox.Sandbox, error) {
return sb, err
}

// checkpointArg resolves a checkpoint_id argument: a handle minted in this
// session when available, else a fresh one — checkpoints outlive sessions.
// checkpointArg resolves a checkpoint_id argument: a handle minted in this session when available, else a fresh one, because checkpoints outlive sessions.
func (s *server) checkpointArg(raw json.RawMessage) (*sandbox.Checkpoint, error) {
var args struct {
CheckpointID string `json:"checkpoint_id"`
Expand Down
2 changes: 1 addition & 1 deletion sandboxd/pool/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ func clampTTL(ttl time.Duration) time.Duration {
return min(ttl, maxTTL)
}

// heldConn keeps its sandbox held until the preview connection closes.
// heldConn keeps its sandbox held until the guest connection closes.
type heldConn struct {
net.Conn
release func()
Expand Down
1 change: 0 additions & 1 deletion sandboxd/server/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ func (s *Server) trackRelay(client, guest net.Conn) (func(), bool) {
}, true
}

// keepAlive bounds a client that dies without a FIN; without it the splice goroutine blocks forever.
func keepAlive(client net.Conn) {
tcp, ok := client.(*net.TCPConn)
if !ok {
Expand Down
12 changes: 6 additions & 6 deletions silkd/src/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ pub enum Chunk {
Exit(i32),
}

#[derive(Clone, Copy)]
enum State {
Running,
Exited(i32),
}

/// Registry of running and recently-exited processes.
#[derive(Clone, Default)]
pub struct Table {
Expand Down Expand Up @@ -242,12 +248,6 @@ impl Ring {
}
}

#[derive(Clone, Copy)]
enum State {
Running,
Exited(i32),
}

/// Stdout/Stderr ride the reused-buffer bulk path; serde's per-chunk allocations dominate replay otherwise.
pub async fn write_chunk<W: AsyncWrite + Unpin>(
w: &mut W,
Expand Down
36 changes: 18 additions & 18 deletions silkd/src/sysutil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,24 +124,6 @@ pub fn adopt_controlling_tty(cmd: &mut Command) {
}
}

/// Makes the calling process a session leader and adopts fd 0 as its controlling terminal.
///
/// # Safety
/// Only async-signal-safe syscalls; valid in a post-fork child.
unsafe fn make_controlling_tty() -> std::io::Result<()> {
// SAFETY: setsid and ioctl are async-signal-safe and take no pointers; the
// caller guarantees a post-fork child (see # Safety).
unsafe {
if libc::setsid() < 0 {
return Err(std::io::Error::last_os_error());
}
if libc::ioctl(0, libc::TIOCSCTTY as _, 0) < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(())
}
}

/// Reads from a raw fd, surfacing WouldBlock to the caller's readiness loop.
pub fn read_fd(fd: RawFd, buf: &mut [u8]) -> std::io::Result<usize> {
// SAFETY: fd is a live open fd; buf is a valid mutable slice of buf.len().
Expand Down Expand Up @@ -181,6 +163,24 @@ pub async fn wait_code(child: &mut tokio::process::Child) -> i32 {
child.wait().await.map_or(-1, exit_code)
}

/// Makes the calling process a session leader and adopts fd 0 as its controlling terminal.
///
/// # Safety
/// Only async-signal-safe syscalls; valid in a post-fork child.
unsafe fn make_controlling_tty() -> std::io::Result<()> {
// SAFETY: setsid and ioctl are async-signal-safe and take no pointers; the
// caller guarantees a post-fork child (see # Safety).
unsafe {
if libc::setsid() < 0 {
return Err(std::io::Error::last_os_error());
}
if libc::ioctl(0, libc::TIOCSCTTY as _, 0) < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(())
}
}

/// Fills `b` from the OS CSPRNG without blocking a tokio worker; /dev/urandom covers the fallback.
fn fill_random(b: &mut [u8]) -> bool {
#[cfg(target_os = "linux")]
Expand Down
4 changes: 1 addition & 3 deletions silkd/tests/forward_e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ async fn forward_round_trips_and_done_on_server_close() {
.await
.expect("test deadline");
}
/// A guest that half-closes must not take the client's write direction with it.
/// What it reads afterwards travels back to the test body: an assertion inside a
/// spawned task is swallowed, so it would pass either way.

async fn half_close_listener() -> (u16, oneshot::Receiver<Vec<u8>>) {
let listener = TcpListener::bind("127.0.0.1:0").await.expect("bind");
let port = listener.local_addr().expect("addr").port();
Expand Down
Loading