Cancel session background processes

This commit is contained in:
wuyang6
2026-06-12 16:24:25 +08:00
parent 953126e1d3
commit 0a3e044c9d
4 changed files with 125 additions and 7 deletions
+45 -4
View File
@@ -2322,6 +2322,11 @@ def create_app(state: AgentState) -> FastAPI:
if payload.run_id and state.run_manager.cancel_run(payload.run_id):
cancelled_ids.add(payload.run_id)
cancelled_ids.update(state.run_manager.cancel_session(account_key, safe_id))
cancelled_bg_task_ids = await _bash_bg_manager.cancel_session(
state,
account_key,
safe_id,
)
stored_cancelled = state.run_state_store.finish_active_for_session(
account_key,
safe_id,
@@ -2329,7 +2334,7 @@ def create_app(state: AgentState) -> FastAPI:
stage='用户已取消',
)
cancelled_ids.update(stored_cancelled)
cancelled = bool(cancelled_ids)
cancelled = bool(cancelled_ids or cancelled_bg_task_ids)
if cancelled:
_mark_session_interrupted(
state.account_paths(payload.account_id)['sessions'],
@@ -2340,6 +2345,7 @@ def create_app(state: AgentState) -> FastAPI:
'session_id': safe_id,
'cancelled': cancelled,
'cancelled_run_ids': sorted(cancelled_ids),
'cancelled_bg_task_ids': sorted(cancelled_bg_task_ids),
}
def _run_chat_payload(
@@ -5832,6 +5838,26 @@ class _BashBackgroundManager:
existing.cancel()
return True
async def cancel_session(
self,
state: 'AgentState',
account_key: str,
session_id: str,
) -> list[str]:
rows = state.bash_bg_store.list_active_for_session(account_key, session_id)
cancelled: list[str] = []
for row in rows:
task_id = str(row.get('task_id') or '')
if not task_id:
continue
await self._kill_remote_or_local(state, row)
state.bash_bg_store.mark_killed(task_id)
existing = self._tasks.pop(task_id, None)
if existing is not None:
existing.cancel()
cancelled.append(task_id)
return cancelled
def status_query(
self, state: 'AgentState', task_id: str
) -> 'BgTaskStatus | None':
@@ -6025,9 +6051,16 @@ class _BashBackgroundManager:
pid = int(row['pid'])
if runtime is not None:
cmd = (
f'kill -- -$(ps -o pgid= -p {pid} 2>/dev/null '
f'| tr -d " ") 2>/dev/null; '
f'kill {pid} 2>/dev/null; true'
f'pgid=$(ps -o pgid= -p {pid} 2>/dev/null | tr -d " "); '
'if [ -n "$pgid" ]; then '
'kill -TERM -- "-$pgid" 2>/dev/null || true; '
'fi; '
f'kill -TERM {pid} 2>/dev/null || true; '
'sleep 0.5; '
'if [ -n "$pgid" ]; then '
'kill -KILL -- "-$pgid" 2>/dev/null || true; '
'fi; '
f'kill -KILL {pid} 2>/dev/null || true'
)
try:
await asyncio.to_thread(
@@ -6047,6 +6080,14 @@ class _BashBackgroundManager:
os.kill(pid, signal.SIGTERM)
except (ProcessLookupError, PermissionError, OSError):
pass
time.sleep(0.2)
try:
os.killpg(os.getpgid(pid), signal.SIGKILL)
except (ProcessLookupError, PermissionError, OSError):
try:
os.kill(pid, signal.SIGKILL)
except (ProcessLookupError, PermissionError, OSError):
pass
async def _maybe_auto_resume(
self, state: 'AgentState', spec: BgTaskSpec, exit_code: int,