Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I kill child processes spawned by the subprocess.Popen() process?

I use subprocess.Popen to spawn a new child process - in this case git clone.

The issue is that git clone itself spawns subprocesses, and when I try to kill them using Popen.kill() only the parent (git clone) gets killed, but not its children.

An example of a child is:

79191 /usr/lib/git-core/git fetch-pack --stateless-rpc --stdin --lock-pack --include-tag --thin --cloning --depth=1 https://example.com/scm/adoha/adoha_digit_interpretation.git/

How can I kill all of the processes - git clone and its children?

NB: I've thought about placing the processes in their own process group, but then the main process gets killed as well.

    # execute a child process using os.execvp()
    p = subprocess.Popen(shlex.split(f'git clone --bare --depth=1 -v \'{url}\' \'{temp_dir}\''),
                         stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    try:
        ret_code = p.wait(timeout)
    except subprocess.TimeoutExpired as exc:
        p.kill()
        shutil.rmtree(temp_dir)
        raise common.exc.WatchdogException(f'Failed to clone repository: Timeout.'
                                           f'\n{timeout=}\n{url=}') from exc
like image 377
Shuzheng Avatar asked Nov 07 '25 19:11

Shuzheng


1 Answers

You can kill a process and its children with this snippet:

import psutil


def kill_process_and_children(pid: int, sig: int = 15):
    try:
        proc = psutil.Process(pid)
    except psutil.NoSuchProcess as e:
        # Maybe log something here
        return

    for child_process in proc.children(recursive=True):
        child_process.send_signal(sig)

    proc.send_signal(sig)

kill_process_and_children(p.pid)
like image 75
RobinFrcd Avatar answered Nov 09 '25 09:11

RobinFrcd