Cancel session background processes
This commit is contained in:
+45
-4
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user