Skip to content

Expose restore_interactive through the C ABI and Python SDK#126

Merged
congwang-mk merged 1 commit into
mainfrom
feat/ffi-restore-interactive
Jul 6, 2026
Merged

Expose restore_interactive through the C ABI and Python SDK#126
congwang-mk merged 1 commit into
mainfrom
feat/ffi-restore-interactive

Conversation

@congwang-mk

@congwang-mk congwang-mk commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Sandbox::restore_interactive() was Rust-only: the C ABI exposed checkpoint capture/save/load/app_state but no way to restore a process image, so the Python SDK could not reach it (Checkpoint.restore only rehydrates app_state). This PR exposes it end to end, with the same shape at every layer: restore returns a handle to the running process, and skipped-fd diagnostics are queryable off the sandbox rather than cluttering the call signature.

  • Core: Sandbox::restore_interactive(&cp) now returns Result<Process<'_>> (matching popen); the process is already running on return. Fds that could not be transparently recreated (sockets, pipes, memfds, pseudo-filesystem paths) are recorded on the Sandbox as structured SkippedFd { fd, path } entries, queryable via Sandbox::restore_skipped().
  • FFI: new sandlock_restore_interactive(policy, name, cp) -> sandlock_handle_t*. The restored process is already running (no sandlock_start); on failure the half-built child is reaped before returning NULL. Skipped fds are enumerated with sandlock_handle_restore_skipped_len / _fd / _path (paths are malloc'd strings freed with sandlock_string_free, lifetime-independent of the handle). include/sandlock.h regenerated with cbindgen.
  • Python: Sandbox.restore_interactive(cp) -> None installs the handle so pid / pause / resume / kill / wait work on the restored process; Sandbox.restore_skipped returns the diagnostics as SkippedFd named tuples. Raises RuntimeError if the sandbox is already running or the restore fails.
  • Docs: python/README.md Sandbox method reference and Checkpoint section.

Inherits the core engine limits: x86_64 only, transparent restore currently holds for vDSO-free programs.

Test plan

  • New crates/sandlock-ffi/tests/restore.rs: end-to-end resume through the C ABI (checkpoint a vDSO-free counter guest, kill it, restore into a fresh handle, prove the counter advances past a sentinel), skipped-fd accessor consistency including out-of-range and NULL-handle sentinels, and a null-input case. Skips gracefully off x86_64 or without a C compiler.
  • New TestRestoreInteractive in python/tests/test_checkpoint.py: the same end-to-end proof through the Python SDK, restore_skipped shape checks, plus the already-running error case.
  • Core build_fd_plan unit tests updated to the structured SkippedFd shape.
  • Full Rust workspace test suite (958 tests, single-threaded) and full Python suite (379 tests) pass locally.

🤖 Generated with Claude Code

@congwang-mk congwang-mk marked this pull request as draft July 6, 2026 05:36
@congwang-mk congwang-mk force-pushed the feat/ffi-restore-interactive branch from 4913182 to 3414266 Compare July 6, 2026 16:59
@congwang-mk congwang-mk marked this pull request as ready for review July 6, 2026 17:03
Signed-off-by: Cong Wang <cwang@multikernel.io>
@congwang-mk congwang-mk force-pushed the feat/ffi-restore-interactive branch from 3414266 to 75ade51 Compare July 6, 2026 17:10
@congwang-mk congwang-mk merged commit 5c9bafe into main Jul 6, 2026
13 checks passed
@congwang-mk congwang-mk deleted the feat/ffi-restore-interactive branch July 6, 2026 20:46
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