Skip to content

Sandbox command locking#395

Merged
robinaugh merged 2 commits intomainfrom
jason/sandbox-command-locking
Mar 5, 2026
Merged

Sandbox command locking#395
robinaugh merged 2 commits intomainfrom
jason/sandbox-command-locking

Conversation

@robinaugh
Copy link
Contributor

@robinaugh robinaugh commented Mar 4, 2026

Blocked by https://github.com/rwx-cloud/mint/pull/3616

Summary

Implements sandbox command locking per RFC 159.

  • Agent-side locking (Layer 2) — Wraps the sandbox exec+sync cycle with __rwx_sandbox_lock_requested__ / __rwx_sandbox_lock_released__ SSH directives to serialize concurrent clients on the same sandbox.
  • Client-side file locking (Layer 0) — Adds advisory flock-based file locking around sandbox storage reads/writes to prevent duplicate sandbox creation by concurrent CLI processes. Lock is scoped to the resolution phase in ExecSandbox, and all other storage-mutating commands (StartSandbox, StopSandbox, ResetSandbox, ListSandboxes) also acquire the lock.

Test plan

  • Unit tests pass (go test ./internal/... ./cmd/...)
  • Manual testing with concurrent sandbox exec commands
  • Verify lock/release directives appear in SSH session output

@robinaugh robinaugh self-assigned this Mar 4, 2026
@robinaugh robinaugh changed the title Sandbox command locking (RFC 159) Sandbox command locking Mar 4, 2026
Acquire __rwx_sandbox_lock_requested__ before executing commands and
release with __rwx_sandbox_lock_released__ after the full exec+sync
cycle completes. This lets the agent serialize concurrent clients on
the same sandbox (Layer 2 from RFC 159).

The lock is always released regardless of command exit code or sync
errors, preventing other clients from being blocked indefinitely.
Use flock to serialize concurrent CLI processes around sandbox
resolution in ExecSandbox (Layer 0 from RFC 159). The lock is
released as soon as a run ID is determined so the actual SSH exec
can proceed concurrently, serialized by the agent-side lock.

All other storage-writing commands (StartSandbox, StopSandbox,
ResetSandbox, ListSandboxes) also acquire the lock so advisory
locking is cooperative across all writers.
@robinaugh robinaugh force-pushed the jason/sandbox-command-locking branch from da5fe96 to a6ae6fc Compare March 4, 2026 21:22
@robinaugh robinaugh marked this pull request as ready for review March 4, 2026 21:49
sessionRunURL = activeSessions[0].RunURL
found = true
} else if len(activeSessions) > 1 {
UnlockSandboxStorage(lockFile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use defer instead of placing this all over?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or are there bits of this that we don't want to hold a lock?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah so we need to explicitly unlock before calling StartSandbox, because it also locks. This ensures we don't have nested attempts to lock that would result in a deadlock.

@robinaugh robinaugh merged commit 7551dc4 into main Mar 5, 2026
1 check passed
@robinaugh robinaugh deleted the jason/sandbox-command-locking branch March 5, 2026 17:08
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.

2 participants