fix(sdk): kill command's whole process tree#1389
Conversation
envd's SendSignal RPC only signals the single process it manages, so child processes spawned by a command kept running (and consuming resources) after kill(). kill() now terminates the command together with its whole process tree. Applied to JS, Python async and sync. Fixes #1034 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR SummaryMedium Risk Overview The same behavior is applied in the JS SDK, Python async, and Python sync command modules; PTY kill paths are unchanged. Tests now assert Reviewed by Cursor Bugbot for commit 4d3f117. Bugbot is set up for automated code reviews on this repo. Configure here. |
🦋 Changeset detectedLatest commit: 4d3f117 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Package ArtifactsBuilt from 347f2ba. Download artifacts from this workflow run. JS SDK ( npm install ./e2b-2.27.2-mishushakov-hyderabad.0.tgzCLI ( npm install ./e2b-cli-2.10.4-mishushakov-hyderabad.0.tgzPython SDK ( pip install ./e2b-2.25.1+mishushakov.hyderabad-py3-none-any.whl |
|
fixing this on envd side |
Problem
Fixes #1034. envd's
SendSignalRPC only signals the single process it manages (thebash -l -cleader), so child processes a command spawned kept running afterkill()— verified on a live sandbox (leaderDEAD, child still alive), which is why the workload kept consuming tokens and "resumed" on reconnect. (The reported "blocking" did not reproduce:kill()returns in ~0.2s even over HTTP/2.)Fix
commands.kill()/ command-handlekill()now terminate the command together with its whole process tree, by running a small shell routine in the sandbox that walks the tree withpgrep -Pand sendsSIGKILLfrom the leaves up (the only mechanism reaching non-envd-managed children); it returns1/0so the found/not-found contract is preserved, and degrades to a single-process kill ifpgrepis unavailable. Applied identically to JS, Python async, and Python sync, with regression tests in all three that capture child PIDs and assert the whole tree is gone (PTY is intentionally untouched).Usage