fix(tools): don't compound-rewrite spawn_via_env background wrappers - #36023
Merged
kshitijk4poor merged 1 commit intoMay 31, 2026
Merged
Conversation
Background tasks on non-local backends (SSH/Docker/Modal/Daytona/Singularity)
go through `ProcessRegistry.spawn_via_env`, which builds a hand-crafted,
shell-safe wrapper:
mkdir -p T && ( nohup bash -lc CMD > LOG 2>&1; rc=$?; ... ) & echo $! > PID && cat PID
`BaseEnvironment.execute()` unconditionally ran `_rewrite_compound_background`
on every command, including this wrapper. The rewrite (meant to defuse the
`A && B &` subshell-wait trap for user commands) turns `( ... ) & echo $!` into
`{ ( ... ) & } echo $!` — note `} echo` with no separator, which is a bash
syntax error. The wrapper then never produces a PID, the redirected output file
is never created, and the agent sees an immediate exit code -1. This breaks
*every* background launch on a non-local backend (e.g. a simple
count-and-redirect script over SSH), not just edge cases.
Fix:
- Add `rewrite_compound_background: bool = True` to `BaseEnvironment.execute()`
(and the `BaseModalExecutionEnvironment` override, which accepts and ignores
it). Default preserves existing behavior; the user foreground terminal path
still rewrites.
- `spawn_via_env` passes `rewrite_compound_background=False` so its already
shell-safe wrapper is left intact.
- Treat a wrapper that produces no PID as a failed launch (mark the session
exited with a real exit code instead of exposing a fake running session), and
don't register/checkpoint a session that never started.
Verified empirically: with the rewrite skipped, the wrapper is valid bash,
launches the process, captures the PID, and writes the log/pid/exit files; the
old rewritten form fails `bash -n` with a syntax error.
Based on NousResearch#33756 by @charzhou (extracted from a multi-feature branch; the
unrelated image_gen / docker-media changes are not included here).
Co-authored-by: CharZhou <17255546+CharZhou@users.noreply.github.com>
kshitijk4poor
enabled auto-merge
May 31, 2026 18:39
Collaborator
alt-glitch
pushed a commit
that referenced
this pull request
Jun 14, 2026
…pper fix(tools): don't compound-rewrite spawn_via_env background wrappers
T02200059
pushed a commit
to T02200059/hermes-agent
that referenced
this pull request
Jun 18, 2026
…a-env-bg-wrapper fix(tools): don't compound-rewrite spawn_via_env background wrappers
waefrebeorn
pushed a commit
to waefrebeorn/slermes
that referenced
this pull request
Jul 2, 2026
…a-env-bg-wrapper fix(tools): don't compound-rewrite spawn_via_env background wrappers
santhreal
pushed a commit
to santhreal/hermes-agent
that referenced
this pull request
Jul 13, 2026
…a-env-bg-wrapper fix(tools): don't compound-rewrite spawn_via_env background wrappers
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
…a-env-bg-wrapper fix(tools): don't compound-rewrite spawn_via_env background wrappers
leewenjie
pushed a commit
to leewenjie/hermes-agent
that referenced
this pull request
Aug 7, 2026
…a-env-bg-wrapper fix(tools): don't compound-rewrite spawn_via_env background wrappers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Salvage of #33756 by @charzhou — fixes background tasks failing to launch on non-local terminal backends (SSH/Docker/Modal/Daytona/Singularity). Extracted as a focused, one-concern PR from the original multi-feature branch (the unrelated image_gen / docker-media changes are intentionally not included).
The bug
Background tasks on non-local backends go through
ProcessRegistry.spawn_via_env, which builds a hand-crafted, shell-safe wrapper:BaseEnvironment.execute()unconditionally ran_rewrite_compound_backgroundon every command — including this wrapper. That rewrite (which defuses theA && B &subshell-wait trap for user commands) turns( ... ) & echo $!into:The wrapper then never produces a PID, the redirected output file is never created, and the agent sees an immediate exit code -1. This breaks every background launch on a non-local backend (e.g. a simple count-and-redirect script over SSH), which is why it reproduces on trivial setups.
Fix
rewrite_compound_background: bool = TruetoBaseEnvironment.execute()(and theBaseModalExecutionEnvironmentoverride, which accepts and ignores it). Default preserves existing behavior; the user foreground terminal path still rewrites.spawn_via_envpassesrewrite_compound_background=Falseso its already shell-safe wrapper is left intact.Changes vs #33756
tools/process_registry.py,tools/environments/base.py,tools/environments/modal_utils.py+ tests). The image_genbase_url/key_envoverrides and docker-media-path changes from the original branch are dropped — those are separate concerns.session.exited = Truein the PID-failure guard._running.@CharZhoutoscripts/release.py::AUTHOR_MAPso release contributor attribution resolves the co-author trailer.Testing
Verified empirically with the exact wrapper shape: skipping the rewrite produces valid bash that launches the process, captures the PID, and writes the log/pid/exit files; the old rewritten form fails
bash -nwith a syntax error.Based on #33756 by @charzhou.