Kill entire process group when stopping a job
Start CLI subprocesses in their own session so SIGTERM via os.killpg reaches child processes (rsync, etc.) not just the shell. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ async def start_cli_process(*args: str) -> asyncio.subprocess.Process:
|
||||
*cmd,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.STDOUT,
|
||||
start_new_session=True,
|
||||
)
|
||||
|
||||
|
||||
|
||||
19
tui/jobs.py
19
tui/jobs.py
@@ -1,4 +1,6 @@
|
||||
import asyncio
|
||||
import os
|
||||
import signal
|
||||
import uuid
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
@@ -77,23 +79,24 @@ class JobManager:
|
||||
app.post_message(JobFinished(job.id, rc))
|
||||
return job.return_code if job.return_code is not None else 1
|
||||
|
||||
@staticmethod
|
||||
def _kill_process_group(proc: asyncio.subprocess.Process) -> None:
|
||||
try:
|
||||
os.killpg(proc.pid, signal.SIGTERM)
|
||||
except (ProcessLookupError, PermissionError):
|
||||
pass
|
||||
|
||||
def kill_job(self, job_id: str) -> bool:
|
||||
job = self._jobs.get(job_id)
|
||||
if not job or job._proc is None:
|
||||
return False
|
||||
try:
|
||||
job._proc.terminate()
|
||||
self._kill_process_group(job._proc)
|
||||
return True
|
||||
except ProcessLookupError:
|
||||
return False
|
||||
|
||||
def kill_running(self) -> None:
|
||||
for job in self._jobs.values():
|
||||
if job._proc is not None:
|
||||
try:
|
||||
job._proc.terminate()
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
self._kill_process_group(job._proc)
|
||||
|
||||
|
||||
job_manager = JobManager()
|
||||
|
||||
Reference in New Issue
Block a user