Skip to content

Replace systemd and start-up.sh with process-compose - #318

Draft
mishushakov wants to merge 1 commit into
mainfrom
cross-platform-process-manager
Draft

Replace systemd and start-up.sh with process-compose#318
mishushakov wants to merge 1 commit into
mainfrom
cross-platform-process-manager

Conversation

@mishushakov

Copy link
Copy Markdown
Member

Jupyter and the code-interpreter server are now supervised by process-compose in both the E2B sandbox and the Docker image, so the two paths can no longer diverge; restart policies, ordering and the ExecStartPre health check gate map over directly, while PartOf=jupyter.service becomes a readiness probe comparing Jupyter's reported start time against the one recorded at gate time (a sticky signal, unlike a liveness check which loses the race — Jupyter recovers in ~1s). Jupyter writes its log file directly rather than through process-compose, because kernels inherit its stdout/stderr and outlive it, and process-compose waits for those descriptors to close before acting on the exit — capturing them left a killed Jupyter unrestarted while any kernel ran, silently breaking the OOM recovery the systemd setup existed for. The restart tests never exercised any of this: pgrep -f 'jupyter server' matched the shell running it, so the kill only ever hit itself and the catch swallowed the error; they now use a bracketed pkill that fails on no match and judge recovery by running code, since the old server answers /health for several seconds while holding dead kernel handles. The debug=True systemd drop-in is gone (logs are always captured now) and debug_logs.py/README point at the new log files.

Verified against a clean Docker build: boot to working execution in 3s, 20s steady state with zero restarts or probe failures, kill Jupyter with kernels alive → both restart and execution works in 7s, kill code-interpreter → only it restarts in 3s. One trade-off: /var/log/jupyter.log is no longer rotated, since process-compose can't capture it; Jupyter can rotate its own log via Application.logging_config, but that sends startup stderr to /dev/null, losing exactly what make debug-template exists to show.

🤖 Generated with Claude Code

Supervise Jupyter and the code-interpreter server with process-compose in
both the E2B sandbox and the Docker image, so the two paths can no longer
diverge. Restart policies, ordering and the ExecStartPre health check gate
map over directly; PartOf=jupyter.service becomes a readiness probe that
compares Jupyter's reported start time against the one recorded at gate
time, which is sticky and so cannot be missed the way a liveness check can.

Jupyter writes its log file directly rather than through process-compose.
Kernels inherit its stdout and stderr and outlive it, and process-compose
waits for those descriptors to close before acting on the exit, so letting
it capture them left a killed Jupyter unrestarted while any kernel ran.

The restart tests never exercised any of this: `pgrep -f 'jupyter server'`
matched the shell running it, so the kill only ever hit itself and the
catch swallowed the error. They now use a bracketed pkill that fails on no
match, and judge recovery by running code, since the old server answers
/health for several seconds while holding dead kernel handles.

Co-Authored-By: Claude <noreply@anthropic.com>
@cla-bot cla-bot Bot added the cla-signed label Jul 29, 2026
@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes how every sandbox boots, supervises, and recovers from Jupyter/OOM kills—core infrastructure with subtle coupling between processes; misconfiguration could break production templates or leave sandboxes unable to execute code.

Overview
Replaces separate systemd (sandbox) and start-up.sh (Docker) supervision with a single process-compose.yaml that boots both environments the same way via process-compose up in template.py.

Jupyter logs go directly to /var/log/jupyter.log so kernels inheriting stdout/stderr do not block restarts. Code-interpreter still gates on jupyter-healthcheck.sh (now also recording Jupyter’s .started in /run/jupyter-instance) and is recycled when Jupyter is replaced via the new jupyter-instance-check.sh readiness probe—replacing systemd’s PartOf=jupyter.service.

Removes systemd units, start-up.sh, and the debug=True journal drop-in; debug_logs.py and the README now point at process-compose and file logs. Restart tests move from systemd.test.ts / test_*_systemd.py to supervision suites using bracketed pkill and waitForWorkingSandbox (runCode) instead of /health alone.

Reviewed by Cursor Bugbot for commit 469b439. Bugbot is set up for automated code reviews on this repo. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant