fix(shell): kill subprocess on CancelledError to prevent orphan processes

When an agent task is cancelled (e.g. via /stop), the ExecTool was only
handling TimeoutError but not CancelledError. This left the child process
running as an orphan. Now CancelledError also triggers process.kill() and
waitpid cleanup before re-raising.
This commit is contained in:
Lingao Meng 2026-04-03 10:20:45 +08:00 committed by Xubin Ren
parent 202938ae73
commit 0e617c32cd

View File

@ -128,6 +128,19 @@ class ExecTool(Tool):
except (ProcessLookupError, ChildProcessError) as e:
logger.debug("Process already reaped or not found: {}", e)
return f"Error: Command timed out after {effective_timeout} seconds"
except asyncio.CancelledError:
process.kill()
try:
await asyncio.wait_for(process.wait(), timeout=5.0)
except asyncio.TimeoutError:
pass
finally:
if sys.platform != "win32":
try:
os.waitpid(process.pid, os.WNOHANG)
except (ProcessLookupError, ChildProcessError) as e:
logger.debug("Process already reaped or not found: {}", e)
raise
output_parts = []