fix(exec): terminate one-shot process trees on cleanup
Run one-shot commands in their own process tree and terminate all descendants after timeout, cancellation, or unexpected failures. Co-authored-by: TRAE CLI <noreply@bytedance.com>
This commit is contained in:
committed by
chengyongru
co-authored by
TRAE CLI
parent
abfcdd481a
commit
d64b84604c
@@ -326,6 +326,7 @@ class ExecTool(Tool):
|
||||
prepared.env,
|
||||
prepared.shell_program,
|
||||
prepared.login,
|
||||
process_tree=True,
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -334,10 +335,10 @@ class ExecTool(Tool):
|
||||
timeout=prepared.timeout,
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
await self._kill_process(process)
|
||||
await self._kill_process_tree(process)
|
||||
return ToolResult.error(f"Error: Command timed out after {prepared.timeout} seconds")
|
||||
except asyncio.CancelledError:
|
||||
await self._kill_process(process)
|
||||
await self._kill_process_tree(process)
|
||||
raise
|
||||
|
||||
# Safety-net reap: asyncio *should* have reaped the child via
|
||||
@@ -374,7 +375,7 @@ class ExecTool(Tool):
|
||||
# Kill and reap the child if it was spawned but an unexpected
|
||||
# error prevented communicate() from completing.
|
||||
if process is not None:
|
||||
await self._kill_process(process)
|
||||
await self._kill_process_tree(process)
|
||||
return ToolResult.error(f"Error executing command: {str(e)}")
|
||||
|
||||
async def _execute_session(
|
||||
|
||||
Reference in New Issue
Block a user