Skip to content

fix(sdk): kill command's whole process tree#1389

Closed
mishushakov wants to merge 1 commit into
mainfrom
mishushakov/hyderabad
Closed

fix(sdk): kill command's whole process tree#1389
mishushakov wants to merge 1 commit into
mainfrom
mishushakov/hyderabad

Conversation

@mishushakov
Copy link
Copy Markdown
Member

Problem

Fixes #1034. envd's SendSignal RPC only signals the single process it manages (the bash -l -c leader), so child processes a command spawned kept running after kill() — verified on a live sandbox (leader DEAD, 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-handle kill() now terminate the command together with its whole process tree, by running a small shell routine in the sandbox that walks the tree with pgrep -P and sends SIGKILL from the leaves up (the only mechanism reaching non-envd-managed children); it returns 1/0 so the found/not-found contract is preserved, and degrades to a single-process kill if pgrep is 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

cmd = await sandbox.commands.run("python agent.py", background=True)
await cmd.kill()  # now also stops every child process the command spawned

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>
@cla-bot cla-bot Bot added the cla-signed label Jun 5, 2026
@cursor
Copy link
Copy Markdown

cursor Bot commented Jun 5, 2026

PR Summary

Medium Risk
Replacing a direct RPC kill with an extra run() inside the sandbox changes process-lifecycle semantics and could behave differently on unusual trees or missing pgrep, though scope is limited to command kill APIs and covered by new integration tests.

Overview
Fixes #1034 by changing how commands.kill() and command-handle kill() stop background work. Instead of envd’s SendSignal SIGKILL (which only hits the managed leader process), kill() now runs a small in-sandbox shell helper that walks descendants with pgrep -P, sends SIGKILL from the leaves up, and prints 1/0 so the existing found / not-found boolean contract stays the same (with a fallback when pgrep is missing).

The same behavior is applied in the JS SDK, Python async, and Python sync command modules; PTY kill paths are unchanged. Tests now assert kill() returns true for a simple process and add a process-tree regression (leader plus two children must all exit).

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

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 5, 2026

🦋 Changeset detected

Latest commit: 4d3f117

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@e2b/python-sdk Patch
e2b Patch

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Package Artifacts

Built from 347f2ba. Download artifacts from this workflow run.

JS SDK (e2b@2.27.2-mishushakov-hyderabad.0):

npm install ./e2b-2.27.2-mishushakov-hyderabad.0.tgz

CLI (@e2b/cli@2.10.4-mishushakov-hyderabad.0):

npm install ./e2b-cli-2.10.4-mishushakov-hyderabad.0.tgz

Python SDK (e2b==2.25.1+mishushakov-hyderabad):

pip install ./e2b-2.25.1+mishushakov.hyderabad-py3-none-any.whl

@mishushakov
Copy link
Copy Markdown
Member Author

fixing this on envd side

@mishushakov mishushakov closed this Jun 5, 2026
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.

Executing AsyncCommandHandle.kill() will cause blocking and cannot kill the process.

1 participant